私の端末でUnicode文字がどのように見えるかを確認するためにこれをシェルスクリプトとして書いています。
#!/bin/bash
X=0
while [ $X -lt 65536 ]; do
HEX=`bc <<< "obase=16; $X"`
HEX="0x${HEX}"
UCODENAME=`printf "%0*x\n" 4 $HEX`
UCODECHAR=`printf "\u%0*x\n" 4 $HEX`
echo -e "Unicode ${UCODENAME} = ${UCODECHAR}"
X=$((X + 1))
done
スクリプトを実行すると、次の出力が表示されます。
print_unicode: line 9: printf: missing unicode digit for \u
Unicode 0188 = ƈ
2行目は私が探しているものです。
printf
私はエラーを取り除くためにこの方法を厳密に使用しようとします。
#!/bin/bash
X=0
while [ $X -lt 65536 ]; do
HEX=`bc <<< "obase=16; $X"`
HEX="0x${HEX}"
printf 'Unicode %0*x = \u%0*x\n' 4 $HEX 4 $HEX
X=$((X + 1))
done
次の結果が表示されます。
print_unicode: line 8: printf: missing unicode digit for \u
Unicode 037f = \u037f
2行目は私が探しているものではなく、同じエラーメッセージが表示されます。
このエラーをどのように解決できますか?
ボーナス:これに対するよりエレガントな解決策は何ですか?
答え1
エラーが発生する理由は次のとおりです。
組み込み printf は、後に実際の数字\U
(または)が続く場合にのみエラーを理解します。\u
$ printf '\U0021'
!
数値を生成して変換するには2段階のprintfが必要です(二重引用符を渡すには大きな\が必要です)。
$ printf '%b' "$(printf '\\U%04X' 33)"
!
あなたが望むように:
$ printf '%b' "$(printf '\\u%0*X' 4 33)"
!
これはまた働きます:
$ printf '%b' "$(printf '\\U%0*X' 8 33)"
!
bashに16進数を伝えるためにbcを使用する必要はありません。
bashはこれをよく理解しています:
$ a=$(( 0xdef )); echo $(( a + 1 ))
3568
数値の16進値を取得するだけでprintf
十分です。
$ printf '0x%06x' 3568
0x000df0
このループは次のように単純化できます。
#!/bin/bash
cp=$((0x020)) len=6
for (( cp=32; cp<$((0x010000)); cp++)); do
Ucode="$(printf '%b' "$(printf '\\U%0*X' "$len" "$cp")")"
printf 'Unicode U%0*x = %s\n' 4 "$cp" "$Ucode"
done
警戒する0x20から0x010000(〜64kライン)まで多くのラインがあります。
UNICODEのコードポイントは最大10FFFFなので、lenを6に増やしました。
もちろん、Ucodeの完全な定義は次のとおりです。
Ucode="$(printf '%b' "$(printf '\\U%0*X' $len "$cp")")"
cp
dec = 32またはHEX = 0x20の下のコードポイント()は制御文字です。
コードがこのようなコードポイントで動作していても、私はそうします。いいえ彼らと遊ぶことをお勧めします。
とは別にUNICODE U0000の場合、値が変数に割り当てられるためです。
この印刷\0
$ printf '%b' "$(printf '\\U%0*X' "6" "0")"
xxdで確認してください:
$ printf '%b' "$(printf '\\U%0*X' "6" "0")" | xxd
0000000: 00
警告する:4.3以下のBashはutf-8からU0080とU00FFの間の値を正しくエンコードできません。バージョン4.3または4.4を使用してください。
答え2
私は努力し続け、解決策を見つけました。
#!/bin/bash
X=0
while [ $X -lt 65536 ]; do
HEX=`bc <<< "obase=16; $X"`
HEX="0x${HEX}"
UCODE=`printf "%0*x\n" 4 $HEX`
printf "Unicode ${UCODE} = \u${UCODE}\n"
X=$((X + 1))
done
私はこのようにprintfを試してみました。 https://stackoverflow.com/questions/5947742/how-to-change-the-output-color-of-echo-in-linux
私はまだもう少しエレガントな解決策を見たいです。
答え3
他の方法でこれを行うことができます(bashはu
エスケープされたバックスラッシュを無視しているようです"\u"
)。
#!/bin/bash
X=0
while [ $X -lt 65536 ]; do
HEX=$(bc <<< "obase=16; $X")
HEX="0x${HEX}"
UCODENAME=$(printf "%0*x\n" 4 $HEX)
UCODECHAR="\\u$(printf "%0*x" 4 $HEX)"
echo -e "Unicode ${UCODENAME} = ${UCODECHAR}"
X=$((X + 1))
done
もちろん、スクリプトはまだbashにのみ適用されます。その他のコメント:
- ほとんどの人はバックティックではなく
$(
andを使用することをお勧めします。)
- bashは
printf
Unicodeを直接印刷できます(エコーは必要ありません)。 - 追加
printf
項目はUCODECHAR
重複しています。
重複排除:
#!/bin/bash
X=0
while [ $X -lt 65536 ]; do
HEX=$(bc <<< "obase=16; $X")
HEX="0x${HEX}"
UCODENAME=$(printf "%0*x\n" 4 $HEX)
UCODECHAR="\\u${UCODENAME}"
echo -e "Unicode ${UCODENAME} = ${UCODECHAR}"
X=$((X + 1))
done