RE erreur: illégal séquence d'octets sur Mac OS X
Je suis en train de remplacer une chaîne de caractères dans un fichier Makefile sur Mac OS X pour la cross-compilation pour iOS. La chaîne a incorporé des guillemets doubles. La commande est:
sed -i "" 's|"iphoneos-cross","llvm-gcc:-O3|"iphoneos-cross","clang:-Os|g' Configure
Et l'erreur est:
sed: RE error: illegal byte sequence
J'ai essayé d'échapper les guillemets doubles, des virgules, des tirets, et les deux-points avec pas de joie. Par exemple:
sed -i "" 's|\"iphoneos-cross\"\,\"llvm-gcc\:\-O3|\"iphoneos-cross\"\,\"clang\:\-Os|g' Configure
Je vais avoir un diable de temps à déboguer le problème. Quelqu'un sait-il comment obtenir sed
pour imprimer la position de l'illégal séquence d'octets? Ou personne ne sait ce que le illégales séquence d'octets est?
- Illégale séquence d'octets sonne comme quelque chose que vous obtenez lors de l'alimentation 8-bit ascii à quelque chose qui s'attend à utf-8.
- Pouvez-vous essayer:
LC_CTYPE=C && LANG=C && sed command
- Merci les gens. Sa a été le
LANG
chose. Soupir.... - Quelqu'un sais comment faire pour déterminer le début de la séquence est marquée comme invalide?
sed -v
provoqué une erreur dans la commande, et leman
pages n'est pas de discuter de la question. - Quelqu'un peut-il m'éclairer comment la ligne de commande peut être valable, avec cet argument vide après la
-i
? - BSD
sed
(également utilisée sur OS X) exige-i ''
(séparée, vide-option de chaîne d'argument) pour la mise à jour sans un fichier de sauvegarde; avec GNUsed
, seulement-i
par lui-même fonctionne - voir stackoverflow.com/a/40777793/45375 - Plus un pour le LANG chose. Bon sang, c'est obscur, non évidente et étonnamment difficile de la recherche.
Vous devez vous connecter pour publier un commentaire.
Un exemple de commande qui présente le symptôme:
sed 's/./@/' <<<$'\xfc'
échoue, car octet0xfc
n'est pas UTF-8 valide char.Notez que, par contraste, GNU
sed
(Linux, mais aussi installable sur macOS) passe tout simplement l'octet non valide à travers, sans rapport d'erreur.À l'aide de la auparavant accepté de répondre à est une option si vous ne me dérange pas de perdre le support pour vos paramètres régionaux (si vous êtes sur un système AMÉRICAIN et vous n'avez jamais besoin de traiter avec des caractères étrangers, qui peuvent être à l'aise.)
Cependant, la même effet peut être dû ad-hoc pour un de commande unique seulement:
Remarque: Ce qui compte c'est un efficace
LC_CTYPE
réglage deC
, doncLC_CTYPE=C sed ...
serait normalement aussi travailler, mais siLC_ALL
arrive à régler (pour autre chose queC
), il remplace individuLC_*
-catégorie de variables telles queLC_CTYPE
. Ainsi, l'approche la plus efficace est de mettre enLC_ALL
.Cependant, (efficacement) réglage
LC_CTYPE
àC
traite les chaînes comme si chaque octet étaient son propre caractère (pas interprétation basée sur des règles de codage est effectué), avec aucun égard pour le multi-octets sur demande - l'encodage UTF-8 que OS X utilise par défaut, où caractères étrangers ont encodages multi-octets.En un mot: réglage
LC_CTYPE
àC
causes de la coquille et des utilitaires pour seulement reconnaître un anglais de base, lettres que lettres (celles de l'ASCII 7 bits de gamme), de sorte que étrangères caractères. ne seront pas traités comme des lettres, provoquant, par exemple, dans le haut-/minuscules conversions à l'échec.Encore une fois, cela peut être bien si vous n'avez pas besoin de match multi-octets caractères codés comme
é
, et veulent simplement passer ces personnages à travers.Si cela est insuffisant et/ou vous souhaitez comprendre la cause de l'erreur d'origine (y compris la détermination de ce que les octets d'entrée est la cause du problème) et effectuer les conversions d'encodage sur demande, lire sur ci-dessous.
Le problème est que l'entrée de codage du fichier ne correspond pas à l'environnement.
Plus précisément, le fichier d'entrée contient des caractères codés d'une manière qui n'est pas valide en UTF-8 (comme @Klas Lindbäck a déclaré dans un commentaire) - qu'est ce que le
sed
message d'erreur est en train de dire parinvalid byte sequence
.Le plus souvent, votre fichier d'entrée utilise un un octet de 8 bits de codage comme
ISO-8859-1
, fréquemment utilisé pour encoder "europe Occidentale" langues.Exemple:
La lettre accentuée
à
a Unicode codepoint0xE0
(224) - le même que dansISO-8859-1
. Toutefois, en raison de la nature de UTF-8 encodage, ce codepoint est représenté comme 2 octets -0xC3 0xA0
, tandis que d'essayer de passer le seul octet0xE0
est invalide en vertu de l'UTF-8.Voici un démonstration du problème l'aide de la chaîne
voilà
codé commeISO-8859-1
, avec laà
représenté comme un octet (via ANSI-C-cité bash chaîne ($'...'
) qui utilise\x{e0}
pour créer de l'octet):Noter que le
sed
commande est effectivement un no-op qui passe tout simplement l'entrée, mais nous en avons besoin pour provoquer l'erreur:Simplement ignorer le problème, le ci-dessus
LCTYPE=C
approche peut être utilisée:Si vous voulez déterminer quelles parties de l'entrée de la cause de ce problème, essayez les solutions suivantes:
La sortie vous montrera tous les octets qui ont la haute ensemble de bits (octets qui dépassent les 7 bits ASCII) dans le format hexadécimal. (Notez, cependant, que, qui comprend également correctement encodé en UTF-8 multi-octets séquences - une approche plus fine serait nécessaire afin de déterminer précisément l'invalide-en-octets UTF-8.)
D'effectuer les conversions d'encodage sur demande:
Utilitaire Standard
iconv
peut être utilisé pour convertir (-t
) et/ou (-f
) codages;iconv -l
listes de toutes les prises en charge.Exemples:
Convertir
ISO-8859-1
pour l'encodage en effet dans le shell (basé surLC_CTYPE
, qui estUTF-8
base par défaut), en s'appuyant sur l'exemple ci-dessus:Noter que cette de conversion vous permet de bien correspondre les caractères étrangers:
Pour convertir l'entrée ARRIÈRE pour
ISO-8859-1
après le traitement, il vous suffit de canaliser le résultat à une autreiconv
commande:LC_CTYPE=C sed 's/.*/&/' <<<$'voil\x{e0}'
imprimesed: RE error: illegal byte sequence
pour moi, sur la Sierra.echo $LC_ALL
sortiesen_US.UTF-8
FWIW.LC_ALL
remplace tous les autresLC_*
variables, y comprisLC_CTYPE
, comme expliqué dans la réponse.Ajoutez les lignes suivantes à votre
~/.bash_profile
ou~/.zshrc
fichier(s).en_GB.UTF-8
(qui est ce que j'ai à l'exportation de LANG déjà dans mon .bash_profile) et obtenir la même erreur. Qu'est-ce que "C" ici?LC_CTYPE
:delorie.com/gnu/docs/gawk/gawk_149.htmlpgrep -f <search_term>
LC_CTYPE
àC
provoque chaque octet de cordes à son propre caractère, sans appliquer des règles d'encodage. Depuis une violation de l' (UTF-8) règles causé le problème d'origine, ce qui rend le problème. Cependant, le prix à payer est que le shell et les utilitaires puis seulement reconnaître les anglais de base des lettres (celles de l'ASCII 7 bits gamme) que les lettres. Voir ma réponse plus.LC_CTYPE=C sed …
, c'est à dire uniquement sur la commande sed.mklement0 réponse est grande, mais j'ai quelques petites modifications.
Il semble être une bonne idée de spécifier explicitement
bash
's l'encodage lors de l'utilisation deiconv
. Aussi, il convient d'ajouter une marque d'ordre d'octet (même si le standard unicode ne le recommande pas) parce que il peut être légitime de confusions entre UTF-8 et ASCII sans une marque d'ordre d'octet. Malheureusement,iconv
ne pas ajouter une marque d'ordre d'octet lorsque vous spécifiez explicitement une endianness (UTF-16BE
ouUTF-16LE
), nous avons donc besoin d'utiliserUTF-16
, qui utilise une plate-forme spécifique endianness, et ensuite utiliserfile --mime-encoding
de découvrir le vrai endiannessiconv
utilisé.(I majuscule tous mes encodages parce que quand vous la liste de tous
iconv
's codage pris en charge aveciconv -l
ils sont tous en majuscules.)file -b --mime-encoding
pour la découverte et la présentation d'un encodage du fichier. Il y a certains aspects convient de prendre en compte, cependant, que je vais faire dans des commentaires séparés.LC_CTYPE
valeur est généralement<lang_region>.UTF-8
, tout fichier sans un BOM (byte-order mark) est donc interprété comme un fichier UTF-8. C'est seulement dans le Windows les pseudo-BOM0xef 0xbb 0xff
est utilisé; par définition, l'UTF-8 ne permet pas de besoin une NOMENCLATURE et n'est pas recommandée (comme vous dites); à l'extérieur du monde de Windows, cette pseudo-NOMENCLATURE des causes de choses à break.Unfortunately, iconv doesn't prepend a byte-order mark when you explicitly specify an endianness (UTF-16BE or UTF-16LE)
: c'est par la conception: si vous spécifiez l'endianness explicitement, il n'y a pas besoin de réfléchir au travers d'une NOMENCLATURE, donc aucun n'est ajouté.locale
va vous montrer ce qu'locale est, en effet, exprimé dans les termes de laLANG
etLC_*
variables d'environnement (etlocale charmap
, comme vous le démontrer, permet d'imprimer le codage des caractères en vigueur).file
retourne ASCII texte brut, mais UTF-8 si je mets un emoji dans le fichier. Cependant, si j'ajoute une NOMENCLATURE,file
retourne toujours UTF-8.LC_*
/LANG
variables:bash
,ksh
, etzsh
(peut-être d'autres, mais pasdash
) faire respecter le codage des caractères; vérifier dans POSIX, comme des coquillages avec un encodage UTF-8 de paramètres régionaux avecv='ä'; echo "${#v}"
: UTF-8 conscient shell devrait rapport1
; c'est à dire, il convient de reconnaître les multi-octet de la séquenceä
(0xc3 0xa4
), comme un unique caractère. Peut-être même plus important encore, cependant: le utilitaires standard (sed
,awk
,cut
, ...) doivent également être locale/encodage de la conscience, et alors que plus de modernes les plateformes de type Unix sont, il ya des exceptions, commeawk
sur OSX, etcut
sur Linux.file
reconnaît l'UTF-8 pseudo-BOM, mais le problème est que la plupart des utilitaires Unix que le processus de fichier pas, et en général s'en sortir ou au moins de mal se conduire face à face. Sans BOM,file
identifie correctement un 7 bits octets de fichiers ASCII et UTF-8 valide de caractères multi-octets en UTF-8. La beauté de l'UTF-8, c'est que c'est un superset de l'ASCII: aucun fichier ASCII est par définition valide d'un fichier UTF-8 (mais pas vice-versa); il est parfaitement sécuritaire pour traiter un fichier ASCII au format UTF-8 (ce qui techniquement est, elle ne contient pas de multi-octets caractères.)Ma solution a été à l'aide de Perl:
Vous avez simplement à pipe d'une iconv commande avant le sed de commande.
Ex avec file.txt entrée :
-f option est le 'de' jeu de caractères et l'option-t est le " à " jeu de caractères de conversion.
Prendre soin de cas, des pages web présentent généralement minuscules comme ça < charset=iso-8859-1"/>
et iconv utilise des majuscules.
Vous avez la liste de iconv pris en charge codesets dans votre système avec la commande iconv -l
UTF8-MAC est moderne OS Mac jeu de caractères pour la conversion.
Ma solution a été d'utiliser gnu
sed
. A bien fonctionné pour mes fins.sed
est une option si vous voulez ignorer invalide octets dans le flux d'entrée (pas besoin de leLC_ALL=C sed ...
solution de contournement), parce que GNUsed
simplement passe invalide octets à l'aide de au lieu de signaler une erreur, mais notez que si vous voulez reconnaître correctement et de traiter tous les caractères dans la chaîne d'entrée, il n'y a pas moyen de contourner changer la source d'entrée de codage du premier (typiquement, aveciconv
).