Ein Beispielbefehl mit dem folgenden Symptom sed 's/./@/' <<<$'\xfc'
schlägt fehl, da das Byte 0xfc
kein gültiges UTF-8-Zeichen ist.
Beachten Sie, dass GNU sed
(Linux, aber auch unter macOS installierbar) das ungültige Byte einfach weiterleitet, ohne einen Fehler zu melden.
Die Verwendung der zuvor akzeptierten Antwort ist eine Option, wenn es Ihnen nichts ausmacht, die Unterstützung für Ihr wahres Gebietsschema zu verlieren (wenn Sie sich in einem US-System befinden und nie mit fremden Zeichen umgehen müssen, kann dies in Ordnung sein.)
Doch das kann die gleiche Wirkung werden mußte Ad-hoc für einen einzigen Befehl nur :
LC_ALL=C sed -i "" 's|"iphoneos-cross","llvm-gcc:-O3|"iphoneos-cross","clang:-Os|g' Configure
Hinweis: Was zählt, ist eine effektive LC_CTYPE
Einstellung von C
, LC_CTYPE=C sed ...
die normalerweise auch funktioniert. Wenn LC_ALL
sie jedoch (auf etwas anderes als C
) eingestellt wird, werden einzelne LC_*
Variablen der Kategorie wie z LC_CTYPE
. Der robusteste Ansatz ist daher das Festlegen LC_ALL
.
Die (effektive) Einstellung LC_CTYPE
, C
Zeichenfolgen so zu behandeln, als ob jedes Byte ein eigenes Zeichen wäre (es wird keine Interpretation basierend auf Codierungsregeln durchgeführt), ohne Berücksichtigung der UTF-8-Codierung (Multibyte-on-Demand) , die OS X standardmäßig verwendet , wo fremde Zeichen haben Multibyte - Codierungen .
Kurz gesagt: Die Einstellung LC_CTYPE
aufC
bewirkt , dass die Shell und die Dienstprogramme nur grundlegende englische Buchstaben als Buchstaben erkennen (diejenigen im 7-Bit-ASCII-Bereich), sodass fremde Zeichen entstehen. werden nicht als Buchstaben behandelt , was beispielsweise dazu führt, dass Konvertierungen in Groß- / Kleinbuchstaben fehlschlagen.
Auch dies kann in Ordnung sein, wenn Sie nicht mit Multibyte-codierten Zeichen wie übereinstimmené
müssen und diese Zeichen einfach weitergeben möchten .
Wenn dies nicht ausreicht und / oder Sie die Ursache des ursprünglichen Fehlers verstehen möchten (einschließlich der Ermittlung, welche Eingabebytes das Problem verursacht haben) und bei Bedarf Codierungskonvertierungen durchführen möchten , lesen Sie weiter unten.
Das Problem ist, dass die Codierung der Eingabedatei nicht mit der der Shell übereinstimmt.
Genauer gesagt, enthält die Eingabedatei in einer Weise codierten Zeichen , die nicht gültig in UTF-8 (als @Klas Lindbäck in einem Kommentar angegeben) - das ist , was die sed
Fehlermeldung von zu sagen versucht invalid byte sequence
.
Höchstwahrscheinlich verwendet Ihre Eingabedatei eine Einzelbyte-8-Bit-Codierung, wie sie ISO-8859-1
häufig zum Codieren von "westeuropäischen" Sprachen verwendet wird.
Beispiel:
Der akzentuierte Buchstabe à
hat den Unicode-Codepunkt 0xE0
(224) - der gleiche wie in ISO-8859-1
. Aufgrund der Art der UTF-8- Codierung wird dieser einzelne Codepunkt jedoch als 2 Byte dargestellt 0xC3 0xA0
, während der Versuch, das einzelne Byte zu übergeben, unter UTF-8 ungültig0xE0
ist .
Hier ist eine Demonstration des Problems unter Verwendung der Zeichenfolge voilà
, die als codiert ist ISO-8859-1
, wobei die Zeichenfolge à
als ein Byte dargestellt wird (über eine in ANSI-C zitierte Bash-Zeichenfolge ( $'...'
), mit \x{e0}
der das Byte erstellt wird):
Beachten Sie, dass der sed
Befehl praktisch ein No-Op ist, der die Eingabe einfach weiterleitet, aber wir brauchen ihn, um den Fehler zu provozieren:
# -> 'illegal byte sequence': byte 0xE0 is not a valid char.
sed 's/.*/&/' <<<$'voil\x{e0}'
Um das Problem einfach zu ignorieren , kann der obige LCTYPE=C
Ansatz verwendet werden:
# No error, bytes are passed through ('á' will render as '?', though).
LC_CTYPE=C sed 's/.*/&/' <<<$'voil\x{e0}'
Wenn Sie feststellen möchten, welche Teile der Eingabe das Problem verursachen , versuchen Sie Folgendes:
# Convert bytes in the 8-bit range (high bit set) to hex. representation.
# -> 'voil\x{e0}'
iconv -f ASCII --byte-subst='\x{%02x}' <<<$'voil\x{e0}'
Die Ausgabe zeigt Ihnen alle Bytes, für die das High-Bit gesetzt ist (Bytes, die den 7-Bit-ASCII-Bereich überschreiten), in hexadezimaler Form. (Beachten Sie jedoch, dass dies auch korrekt codierte UTF-8-Multibyte-Sequenzen umfasst - ein komplexerer Ansatz wäre erforderlich, um In-UTF-8-Bytes spezifisch ungültig zu identifizieren.)
Codierungskonvertierungen bei Bedarf durchführen :
Das Standarddienstprogramm iconv
kann zum Konvertieren in ( -t
) und / oder von ( -f
) -Codierungen verwendet werden. iconv -l
listet alle unterstützten auf.
Beispiele:
Konvertieren Sie FROM ISO-8859-1
in die in der Shell gültige Codierung (basierend auf LC_CTYPE
, die UTF-8
standardmäßig basiert ), basierend auf dem obigen Beispiel:
# Converts to UTF-8; output renders correctly as 'voilà'
sed 's/.*/&/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')"
Beachten Sie, dass Sie mit dieser Konvertierung Fremdzeichen richtig abgleichen können :
# Correctly matches 'à' and replaces it with 'ü': -> 'voilü'
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')"
Um die Eingabe ISO-8859-1
nach der Verarbeitung wieder in umzuwandeln, leiten Sie das Ergebnis einfach an einen anderen iconv
Befehl weiter:
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')" | iconv -t ISO-8859-1