Bash
為什麼我收到錯誤“print_unicode:第 9 行:printf:缺少 u Unicode 0187 的 unicode 數字”使用此腳本
我已經按照 shell 腳本編寫了它們,以查看 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 = ƈ
第二行正是我正在尋找的。
我確實嘗試嚴格使用
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
第二行不是我要找的,我仍然收到相同的錯誤消息。
如何修復此錯誤?
獎勵:對此有什麼更優雅的解決方案?
您得到錯誤的原因是:
內置 printf僅在
\U
(or\u
) 後跟一個實際數字時才理解:$ printf '\U0021' !
要使其創建數字並進行轉換,需要兩步 printf (需要雙 \ 才能通過雙引號):
$ printf '%b' "$(printf '\\U%04X' 33)" !
如你所願:
$ printf '%b' "$(printf '\\u%0*X' 4 33)" !
這也有效:
$ printf '%b' "$(printf '\\U%0*X' 8 33)" !
不需要使用 bc 來告訴 bash 十六進制數字。
bash 可以很好地理解這一點:
$ a=$(( 0xdef )); echo $(( a + 1 )) 3568
並且獲得一個數字的十六進制值
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 行)。
我將 len 增加到 6,因為 UNICODE 的程式碼點最高可達 10FFFF。
當然,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
CAVEAT:低於 4.3 的 Bash 無法正確編碼 utf-8 中 U0080 和 U00FF 之間的值。請使用版本 4.3 或 4.4 。