Text-Processing

不能將 cut -c (--characters) 與 UTF-8 一起使用?

  • January 6, 2021

該命令cut具有-c處理字元的選項,而不是帶有選項的字節-b。但這似乎不起作用,在en_US.UTF-8語言環境中:

第二個字節給出了第二個 ASCII 字元(在 UTF-8 中編碼相同):

$ printf 'ABC' | cut -b 2          
B

但在 UTF-8 語言環境中不給出三個希臘非 ASCII 字元中的第二個:

$ printf 'αβγ' | cut -b 2         
�

沒關係 - 這是第二個字節

所以我們看第二個字元

$ printf 'αβγ' | cut -c 2 
�

那看起來壞了。

通過一些實驗,結果表明範圍3-4顯示了第二個字元:

$ printf 'αβγ' | cut -c 3-4
β

但這與字節 3 到 4 相同:

$ printf 'αβγ' | cut -b 3-4
β

所以-c不超過-bUTF-8 的。

我希望語言環境設置不適合 UTF-8,但相比之下,wc可以按預期工作;

它通常用於計算字節數,帶有選項-c( --bytes)。 (注意令人困惑的選項名稱。)

$ printf 'αβγ' | wc -c
6

但它也可以使用選項-m( --chars) 計算字元,這很有效:

$ printf 'αβγ' | wc -m
3

所以我的配置似乎還可以——但有些特別之處cut

也許它根本不支持 UTF-8?但它似乎確實支持多字節字元,否則它不需要支持-band -c

那麼,怎麼了?為什麼?

據我所知,語言環境設置看起來適合 utf8:

$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_CTYPE=en_US.UTF-8
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

輸入,逐字節:

$ printf 'αβγ' | hd 
00000000  ce b1 ce b2 ce b3                                 |......|
00000006

你還沒有說cut你正在使用哪個,但既然你提到了 GNU long 選項--characters,我會假設它就是那個。在這種情況下,請注意以下段落info coreutils 'cut invocation'

‘-c character-list’
‘--characters=character-list’

選擇僅列印字元列表中列出的位置中的字元。和現在****一樣-b,但國際化會改變這一點。

(重點補充)

目前,GNUcut始終根據單字節“字元”工作,因此您看到的行為是預期的。


POSIX 需要同時支持-b-c選項——它們沒有被添加到 GNU 中,因為它支持多字節並且它們工作正常,但是為了避免在符合 POSIX 的輸入上出現錯誤。在其他一些實現中也是如此,儘管至少在FreeBSDOS X中沒有。cut``-c``cut

這是歷史的行為。新添加來接管字節角色,以便可以處理多字節字元。也許幾年後它會始終如一地工作,儘管進展並不是很快(已經十多年了)。GNU甚至還沒有實現該選項,儘管它是正交的並且旨在幫助過渡。舊腳本存在潛在的兼容性問題,這可能是一個問題,儘管我不確定原因是什麼。-c``-b``-c``cut -n

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