sed 's/./@/' <<<$'\xfc'
バイト0xfc
が有効なUTF-8文字ではないため、症状を示すサンプルコマンドは失敗します。
対照的に、GNU sed
(Linux、macOSにもインストール可能)は、エラーを報告せずに、無効なバイトを単に通過させることに注意してください。
以前に受け入れられた回答の使用は、真のロケールのサポートを失うことを気にしない場合のオプションです(米国のシステムを使用していて、外国の文字を処理する必要がない場合は、問題ないかもしれません)。
ただし、同じ効果は、1つのコマンドに対してのみアドホックにできます。
LC_ALL=C sed -i "" 's|"iphoneos-cross","llvm-gcc:-O3|"iphoneos-cross","clang:-Os|g' Configure
注:どのような重要なのである効果 LC_CTYPE
の設定C
、そうLC_CTYPE=C sed ...
でしょう、通常ならば、作業が、LC_ALL
(以外に設定することを起こるC
)、それは個々の優先されますLC_*
よう-category変数をLC_CTYPE
。したがって、最も堅牢なアプローチはを設定することLC_ALL
です。
しかし、(効果)の設定LC_CTYPE
にC
扱い、文字列の各バイトは、独自の文字であるかのように(何もして、エンコードルールに基づいて解釈が実行されません)なしについて -マルチバイト・オン・デマンド-のためのUTF-8エンコーディング OS Xはデフォルトで採用していることここで、外部文字にはマルチバイトエンコーディングが使用されます。
一言で言えば、シェルとユーティリティが基本的な英語の文字(7ビットASCII範囲の文字)のみを認識するように設定LC_CTYPE
するC
と、外部の文字になります。は文字として扱われないため、たとえば、大文字と小文字の変換が失敗します。
この場合も、などのマルチバイトでエンコードされた文字を一致させる必要がなくé
、単にそのような文字をに通したい場合は、これで問題ありません。
これで不十分な場合や、元のエラーの原因(問題の原因となった入力バイトの特定など)を理解し、必要に応じてエンコード変換を実行する場合は、以下をお読みください。
問題は、入力ファイルのエンコーディングがシェルのエンコーディングと一致しないことです。
より具体的には、入力ファイルには、UTF-8では無効な方法でエンコードされた文字が含まれています(@KlasLindbäckがコメントで述べているように)。これsed
が、エラーメッセージがによって伝えようとしていることinvalid byte sequence
です。
ほとんどの場合、入力ファイルは、「西ヨーロッパ」言語のエンコードに頻繁に使用されるなどのシングルバイト8ビットエンコーディングをISO-8859-1
使用します。
例:
アクセント付きの文字にà
はUnicodeコードポイント0xE0
(224)が含まれていISO-8859-1
ます-と同じです。ただし、UTF-8エンコーディングの性質上、この単一のコードポイントは2バイト- として表されますが、UTF-8では単一バイト0xC3 0xA0
を渡そうとすることは無効です。 0xE0
ここだ問題のデモの文字列を使用してvoilà
のようにエンコードISO-8859-1
して、à
として表さ1(ANSI-C-引用されたbashの文字列(経由バイト$'...'
の用途があること)\x{e0}
のバイトを作成するには):
sed
コマンドは事実上、単に入力を渡すだけの何もしないことに注意してください。ただし、エラーを引き起こすために必要です。
# -> 'illegal byte sequence': byte 0xE0 is not a valid char.
sed 's/.*/&/' <<<$'voil\x{e0}'
問題を単に無視するには、上記のLCTYPE=C
アプローチを使用できます。
# No error, bytes are passed through ('á' will render as '?', though).
LC_CTYPE=C sed 's/.*/&/' <<<$'voil\x{e0}'
入力のどの部分が問題の原因であるかを特定する場合は、次のことを試してください。
# 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}'
出力には、上位ビットが設定されているすべてのバイト(7ビットのASCII範囲を超えるバイト)が16進数形式で表示されます。(ただし、これには正しくエンコードされたUTF-8マルチバイトシーケンスも含まれることに注意してください。UTF-8で無効なバイトを明確に識別するには、より洗練されたアプローチが必要になります。)
オンデマンドでエンコード変換を実行する:
標準ユーティリティiconv
を使用して、(-t
)および/または(-f
)エンコーディングに変換できます。iconv -l
サポートされているものをすべてリストします。
例:
上記の例にISO-8859-1
基づいてLC_CTYPE
、FROM をシェルで有効なエンコーディング(UTF-8
デフォルトでは-basedに基づく)に変換します。
# Converts to UTF-8; output renders correctly as 'voilà'
sed 's/.*/&/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')"
この変換により、外部文字を適切に一致させることができることに注意してください。
# Correctly matches 'à' and replaces it with 'ü': -> 'voilü'
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')"
入力BACKをISO-8859-1
処理後にに変換するには、結果を別のiconv
コマンドにパイプするだけです。
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')" | iconv -t ISO-8859-1