這在使用 unicode 字符時不起作用(在 Ubuntu bash 中):
$ perl -pC -e's/[à]/a/gu' <<< 'à'
à
$ perl -pC -e's/[b]/a/gu' <<< 'b'
a
盡管 PCRE 似乎支持它(至少根據regex101)。
我究竟做錯了什么?我在 perl 命令中遺漏了一些標志嗎?
這在 javascript 中“正常作業”,所以如果我能在命令列中為此提供一個簡單的單行代碼,我將使用 node ......但我仍然想知道為什么 perl 命令不起作用。
對于背景關系:
我試圖使用像換人/[àaá??]/a/g,/[ò?ó??]/o/g等來asciify字典檔案(即洗掉口音,一個單詞表等),這樣我就可以用它來作拼寫檢查不區分重音(如的IntelliJ IDEA)。
基本上這些是制作“asciified”額外字典的步驟:
- 下載該語言的 .dic 檔案(所有單詞的串列)
- 使用 grep 過濾包含非 ascii / 可替換字符的單詞
- 連續使用正則運算式替換使單詞不區分重音
- 在 IDE 中匯入 asciified .dic 檔案(除了標準語言詞典)
uj5u.com熱心網友回復:
所有這些的一種實用方法是使用Text::Unidecode
perl -C -MText::Unidecode -pe'unidecode($_)' <<< 'à'
列印a。該模塊將 Unicode 文本音譯為純 ASCII。
另一種方法:使用分解字符(“正常化”)的Unicode ::正常化,使角色和它的變音符號(合并重音)分離成自己的代碼點,而他們仍然形成有效的字形,然后取出變音符號(\p{NonspacingMark}或\p{Mn}) 用一個簡單的正則運算式。
這兩種方式都會有例外和邊緣情況,但我認為它可能只是做你需要的。
對于包含特定(文字)字符的代碼,需要通過utf8 pragma withuse utf8;或命令列標志告訴 Perl 程式源是 UTF-8-Mutf8
perl -C -Mutf8 -pe's/[à]/a/g' <<< 'à'
uj5u.com熱心網友回復:
您需要添加-Mutf8以告訴 Perl 程式是使用 UTF-8 而不是 ASCII 編碼的。
$ perl -pC -Mutf8 -e's/[à]/a/gu' <<< 'à'
a
uj5u.com熱心網友回復:
下面是我如何實作第 2 步和第 3 步。
這可以用于,例如,在這些字典中(盡管我沒有在每種語言上測驗它)。
asciify-dic
#!/usr/bin/env bash
#License: "Zero-Clause BSD" <https://opensource.org/licenses/0BSD>
if [[ "$1" == "--help" ]]; then
echo "Usage: $(basename "$0") INPUT_FILE > OUTPUT_FILE"
echo "Asciify a .dic file (list of dictionary words)."
echo ""
echo "Generates a file with ASCII-only versions of the words that have non-ASCII chars."
echo "These additional words can be used to make spell-checking accent-insensitive."
echo "Comment lines beginning with % are left unchanged."
exit
fi
# Filter words containing non-ascii characters, except in comments
grep -P '^\%|[^\x00-\x7F]' $1 |
# Make words accent-insensitive, except in comments
perl -C -MText::Unidecode -pe'next if /^\s*%/;unidecode($_)' |
# Remove duplicate lines, except in comments
awk '/^\s*%/||!seen[$0] '
用法示例:
asciify-dic $DIC_NAME.dic > $DIC_NAME-asciified.dic
uj5u.com熱心網友回復:
簡短的回答是添加-Mutf8到您的命令列。
如果你不確定 Perl 如何解釋你在命令列上寫的東西,你可以讓它用核心B::perlstring()函式把它吐回給你,或者用B::Deparse. 這將很快說明您的問題。(將 'à' 字符括在方括號中在這里沒有任何作用。)
$ perl -MO=Deparse -pC -e 's/à/a/gu' <<< 'à'
LINE: while (defined($_ = <ARGV>)) {
s/\303\240/a/gu;
}
continue {
die "-p destination: $!\n" unless print $_;
}
-e syntax OK
看看你的替代品是如何巧妙地包含 2 個字符的?
然后您可以立即看到如何use utf8解決您的問題。
$ perl -MO=Deparse -Mutf8 -pC -e 's/à/a/gu' <<< 'à'
use utf8;
LINE: while (defined($_ = <ARGV>)) {
s/\340/a/gu;
}
continue {
die "-p destination: $!\n" unless print $_;
}
-e syntax OK
您可以使用perlstring()來確保 Perl 正在接收您認為的輸入。
$ perl -p -MB -E 'say B::perlstring($_)' <<< 'à'
"\303\240\n"
à
$ perl -pC -MB -E 'say B::perlstring($_)' <<< 'à'
"\x{e0}\n"
à
您可以看到沒有-CPerl 的情況下會收到 2 個分解字符。
根據情況,Perl 將字符轉儲為八進制代碼 ( \340) 或十六進制代碼 ( \xE0)。請注意,您始終可以將命令列中的原始 unicode 字符替換為轉義碼版本。這是一個很好的方式來明確什么否則會模棱兩可。
$ perl -pC -e 's/[\xE0]/a/gu' <<< 'à'
a
如果您不想記住 UTF8 模式,您可以將這些選項推送到PERL5OPT環境變數中或創建一個 shell 別名。小心使這成為全球性的!
$ export PERL5OPT='-C -Mutf8'
$ perl -MO=Deparse -p -e 's/à/a/gu' <<< 'à'
use utf8;
LINE: while (defined($_ = <ARGV>)) {
s/\340/a/gu;
}
continue {
die "-p destination: $!\n" unless print $_;
}
-e syntax OK
$ perl -MB -p -E 'say B::perlstring($_)' <<< 'à'
"\x{e0}\n"
à
或者作為 shell 別名。
alias uperl='perl -C -Mutf8'
有關如何使用 Swiss Army Chainsaw 命令列的更多資訊,請參閱perlrun。
另見B::Deparse。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/383282.html
上一篇:在Perl中按順序列印哈希鍵
