🤖

【Bash】文字列とバイト列、ユニコードエスケープシーケンスの相互変換

2023/07/11に公開

Bash はバイト列やユニコードのエスケープシーケンスをサポートする。

echo -e "\xe3\x81\x82"
echo -e \\xe3\\x81\\x82"
echo -e "\u3042"
echo -e \\u3042

コードポイントから文字を生成するには printf によるユニコードエスケープシーケンスの生成を利用する。

printf $(printf '\\U%08x' 0x3042)\\n

文字からコードポイントを求める場合、文字の前にシングルクォートをつける。

printf U+%X\\n \'あ
U+3042

POSIX の仕様ではシングルクォートやダブルクォートではじまる文字は数値として扱われる[1]。

1 http://mywiki.wooledge.org/BashFAQ/071

文字からバイト列のエスケープシーケンスを生成するには hexdump を使う。

echo -n| hexdump -e '"\\\x" 1/1 "%02x"'; echo;
\xe3\x81\x82

エスケープシーケンスではない16進数の並びであれば xxd が使える。

echo -n| xxd -p
e38182
echo -n e38182 | xxd -r -p; echo

文字列から文字を1つずつ取り出すには for 文とインデックス表記を利用する。

str=あいうえお; for ((i=0; i<${#str}; i++)); do echo ${str:$i:1}; done
あ
い
う
え
お

for-in 文の場合、sed を組み合わせる。

for c in $(sed 's/./&\n/g' <(printf あいうえお)); do echo $c; done
あ
い
う
え
お

sedgawkgrep のワンライナーも利用できる。

echo -n あいうえお | sed -e 's/\(.\)/\1\n/g'
echo -n あいうえお | gawk '{ gsub(/./, "&\n"); print }'
echo -n あいうえお | grep -Eo '.{1}'

調査した時点では拡張書記素クラスターをサポートするコマンドツールは見つからなかった。ツールを開発するには拡張書記素クラスターをサポートする正規表現ライブラリや ICU が必要になる。

【2024年7月追記】
GUN grep は PCRE 2 をサポートしている。くわしくはこちらの記事を参照

echo -e "ハ\u309A\u309A"
パパ
echo -e "ハ\u309A\u309A" | grep -oP '\X'
パ
パ

Discussion