Mac の sed とか tr が illegal byte sequence エラーになるときの回避方法のメモ。
sed とか tr が illegal byte sequence エラーになる
どんなことがおきるか
sed とか tr が illegal byte sequence エラーになってしまうことがある。
たとえば ascii 文字のうち英字と数字だけを表示するのをやってみるとこんな感じにエラーになる。 tr のほうはエラーメッセージを表示と一応は英数字を出力してるけど sed のほうは完全に沈黙してる感じ。
$ awk 'BEGIN{for(i=0;i<256;i++){printf("%c",i)}}' | tr -dc "[:alnum:]"
tr: Illegal byte sequence
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
$ awk 'BEGIN{for(i=0;i<256;i++){printf("%c",i)}}' | sed -E 's/[^a-zA-Z0-9]//g'
sed: RE error: illegal byte sequence
どうしたら回避できるか
こういうときは LC_CTYPE=C を指定して sed とか tr を実行すると illegal byte sequence エラーは回避できる。
$ awk 'BEGIN{for(i=0;i<256;i++){printf("%c",i)}}' | LC_CTYPE=C tr -dc "[:alnum:]"
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
$ awk 'BEGIN{for(i=0;i<256;i++){printf("%c",i)}}' | LC_CTYPE=C sed -E 's/[^a-zA-Z0-9]//g'
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
ただ LC_ALL が指定してあると LC_ALL は LC_CTYPE より優先されるので LC_CTYPE=C を指定しても illegal byte sequence エラーになっちゃう。
$ locale | grep LC_ALL
LC_ALL="ja_JP.UTF-8"
$ awk 'BEGIN{for(i=0;i<256;i++){printf("%c",i)}}' | LC_CTYPE=C tr -dc "[:alnum:]"
tr: Illegal byte sequence
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
$ awk 'BEGIN{for(i=0;i<256;i++){printf("%c",i)}}' | LC_CTYPE=C sed -E 's/[^a-zA-Z0-9]//g'
sed: RE error: illegal byte sequence
LC_ALL が指定してあるときは LC_ALL=C を指定して sed とか tr を実行すると illegal byte sequence エラーを回避できる。
$ awk 'BEGIN{for(i=0;i<256;i++){printf("%c",i)}}' | LC_ALL=C tr -dc "[:print:]"
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
$ awk 'BEGIN{for(i=0;i<256;i++){printf("%c",i)}}' | LC_ALL=C sed -E 's/[^a-zA-Z0-9]//g'
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz