Un exemple de commande qui présente le symptôme: sed 's/./@/' <<<$'\xfc'échoue, car l'octet 0xfcn'est pas un caractère UTF-8 valide.
Notez que, en revanche, GNU sed (Linux, mais également installable sur macOS) passe simplement l'octet invalide, sans signaler d'erreur.
L'utilisation de la réponse précédemment acceptée est une option si cela ne vous dérange pas de perdre la prise en charge de votre véritable locale (si vous êtes sur un système américain et que vous n'avez jamais besoin de gérer des caractères étrangers, cela peut être bien.)
Cependant, le même effet peut être obtenu ad hoc pour une seule commande uniquement :
LC_ALL=C sed -i "" 's|"iphoneos-cross","llvm-gcc:-O3|"iphoneos-cross","clang:-Os|g' Configure
Remarque: Ce qui compte, c'est un réglage efficace LC_CTYPE de C, donc LC_CTYPE=C sed ...cela fonctionnerait normalement aussi, mais s'il LC_ALLse trouve être défini (sur autre chose que C), il remplacera les LC_*variables de catégorie individuelles telles que LC_CTYPE. Ainsi, l'approche la plus robuste est de définir LC_ALL.
Cependant, le réglage (effectivement) LC_CTYPEsur Ctraite les chaînes comme si chaque octet était son propre caractère ( aucune interprétation basée sur des règles de codage n'est effectuée), sans égard pour le codage UTF-8 multi-octets à la demande qu'OS X utilise par défaut , où les caractères étrangers ont des encodages multi - octets .
En un mot: le réglage LC_CTYPEsurC fait que le shell et les utilitaires ne reconnaissent que les lettres anglaises de base comme des lettres (celles de la plage ASCII 7 bits), de sorte que les caractères étrangers. ne seront pas traités comme des lettres , ce qui entraînera, par exemple, l'échec des conversions majuscules / minuscules.
Encore une fois, cela peut convenir si vous n'avez pas besoin de faire correspondre des caractères codés sur plusieurs octets tels que é, et que vous souhaitez simplement passer ces caractères .
Si cela est insuffisant et / ou si vous souhaitez comprendre la cause de l'erreur d'origine (y compris déterminer quels octets d'entrée ont causé le problème) et effectuer des conversions de codage à la demande, lisez la suite ci-dessous.
Le problème est que le codage du fichier d'entrée ne correspond pas à celui du shell.
Plus précisément, le fichier d'entrée contient des caractères encodés d'une manière qui n'est pas valide en UTF-8 (comme @Klas Lindbäck l'a déclaré dans un commentaire) - c'est ce que le sedmessage d'erreur essaie de dire invalid byte sequence.
Très probablement, votre fichier d'entrée utilise un codage 8 bits à un octet tel que ISO-8859-1, fréquemment utilisé pour coder les langues «d'Europe occidentale».
Exemple:
La lettre accentuée àa un point de code Unicode 0xE0(224) - le même que dans ISO-8859-1. Cependant, en raison de la nature du codage UTF-8 , ce point de code unique est représenté par 2 octets - 0xC3 0xA0, alors que tenter de passer l' octet unique 0xE0 est invalide sous UTF-8.
Voici une démonstration du problème en utilisant la chaîne voilàcodée comme ISO-8859-1, avec le àreprésenté comme un octet (via une chaîne bash entre guillemets ANSI-C ( $'...') qui utilise \x{e0}pour créer l'octet):
Notez que la sedcommande est effectivement un no-op qui passe simplement l'entrée, mais nous en avons besoin pour provoquer l'erreur:
sed 's/.*/&/' <<<$'voil\x{e0}'
Pour ignorer simplement le problème , l' LCTYPE=Capproche ci-dessus peut être utilisée:
LC_CTYPE=C sed 's/.*/&/' <<<$'voil\x{e0}'
Si vous souhaitez déterminer quelles parties de l'entrée sont à l'origine du problème , essayez ce qui suit:
iconv -f ASCII --byte-subst='\x{%02x}' <<<$'voil\x{e0}'
La sortie vous montrera tous les octets qui ont le bit haut défini (octets qui dépassent la plage ASCII 7 bits) sous forme hexadécimale. (Notez, cependant, que cela inclut également les séquences multioctets UTF-8 correctement codées - une approche plus sophistiquée serait nécessaire pour identifier spécifiquement les octets non valides en UTF-8.)
Effectuer des conversions d'encodage à la demande :
L'utilitaire standard iconvpeut être utilisé pour convertir des encodages en ( -t) et / ou à partir de ( -f); iconv -lrépertorie tous ceux pris en charge.
Exemples:
Convertissez FROM ISO-8859-1en encodage en vigueur dans le shell (basé sur LC_CTYPE, qui est UTF-8basé par défaut), en vous basant sur l'exemple ci-dessus:
sed 's/.*/&/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')"
Notez que cette conversion vous permet de faire correspondre correctement les caractères étrangers :
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')"
Pour convertir l'entrée BACK en ISO-8859-1après traitement, dirigez simplement le résultat vers une autre iconvcommande:
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')" | iconv -t ISO-8859-1