Bash

為什麼我收到錯誤“print_unicode:第 9 行:printf:缺少 u Unicode 0187 的 unicode 數字”使用此腳本

  • March 31, 2016

我已經按照 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")")"

請注意,cpdec=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 。

引用自:https://unix.stackexchange.com/questions/272982