用於unicode字元的tr模擬?
我需要與以下功能相同的國際化實用程序
tr
:從流中獲取字元並將其替換為相應的字元。不是像從下到上的特定案例解決方案,而是需要一般案例解決方案。如果可能的話,沒有 gorillion 管道sed
呼叫。請注意,
tr
這在 Linux 上不起作用:它轉換字節,而不是字元。多字節編碼失敗。$ tr --version | head -n 1 tr (GNU coreutils) 8.23 $ echo $LC_CTYPE en_US.UTF-8 $ echo 'Ångstrom' | tr Æ Œ Ņngstrom
GNU
sed
確實可以處理多字節字元。所以:$ echo é½Æ | sed 'y/é½Æ/ABŒ/' ABŒ
不是 GNU
tr
沒有國際化,而是它不支持多字節字元(如 UTF-8 語言環境中的非 ASCII 字元)。只要它們像 iso8859-15 字元集中那樣是單字節的,GNUtr
就可以使用。Æ``Œ
更多關於如何讓 tr 了解非 ascii(unicode) 字元?
無論如何,這與Linux無關,它
tr
與系統上的實現有關。該系統是使用 Linux 作為核心還是tr
為 Linux 建構或使用 Linux 核心 API 並不相關,因為這部分tr
功能發生在使用者空間中。busybox
tr
和 GNUtr
是為 Linux 建構的軟體發行版中最常見的,它們不支持多字節字元,但還有其他一些已移植到 Linuxtr
,例如 heirloom toolchest(從 OpenSolaris 移植)或 ast-打開那個做。請注意,
sed
’y
不支持a-z
. 另請注意,如果包含sed 'y/é½Æ/ABŒ/'
的腳本以 UTF-8 字元集編寫,則如果在 UTF-8 不是字元集的語言環境中呼叫,它將不再按預期工作。另一種方法是使用
perl
:perl -Mopen=locale -Mutf8 -pe 'y/a-zé½Æ/A-ZABŒ/'
上面,perl 程式碼應該是 UTF-8 格式,但它會以區域設置的編碼處理輸入(並以相同的編碼輸出)。如果在 UTF-8 語言環境中呼叫,它會將 UTF-8
Æ
(0xc3 0x86) 音譯為 UTF-8Œ
(0xc5 0x92),並且在 ISO8859-15 中相同,但 0xc6 -> 0xbc。在大多數 shell 中,即使在 UTF-8 不是字元集的語言環境中呼叫腳本,在單引號內包含這些 UTF-8 字元也應該沒問題(
yash
如果這些字節不形成有效字元,則會報錯在語言環境中)。但是,如果您使用的是單引號以外的其他引用,則可能會導致問題。例如,perl -Mopen=locale -Mutf8 -pe "y/♣\`/&'/"
在字元集為 BIG5-HKSCS 的語言環境中會失敗,因為
\
(0x5c) 的編碼也恰好包含在那裡的一些其他字元中(例如α
:0xa3 0x5c,而 UTF-8 編碼♣
恰好以 0xa3 結尾)。無論如何,不要指望像
perl -Mopen=locale -Mutf8 -pe 'y/Á-Ź/A-Z/'
致力於消除尖銳的口音。以上其實只是
perl -Mopen=locale -Mutf8 -pe 'y/\x{c1}-\x{179}/\x{41}-\x{5a}/'
也就是說,範圍基於 unicode 程式碼點。因此,在 Unicode中恰好處於“正確
A-Z
”順序的定義非常明確的序列(例如,0-9
.如果要刪除尖銳的口音,則必須使用更高級的工具,例如:
perl -Mopen=locale -MUnicode::Normalize -pe ' $_ = NFKD($_); s/\x{301}//g; $_ = NFKC($_)'
那就是使用 Unicode 規範化形式來分解字元,刪除尖銳的重音(這裡是組合形式
U+0301
)並重新組合。另一個用於音譯 Unicode 的有用工具
uconv
來自ICU。例如,上面的也可以寫成:uconv -x '::NFKD; \u0301>; ::NFKC;'
雖然只適用於 UTF-8 數據。你需要:
iconv -t utf-8 | uconv -x '::NFKD; \u0301>; ::NFKC;' | iconv -f utf-8
能夠在使用者的語言環境中處理數據。