如何在perl regex替换命令中使用unicode字符?

omqzjyyz  于 2022-11-15  发布在  Perl
关注(0)|答案(4)|浏览(170)

在使用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/g/[òôóõö]/o/g等替换来关联字典文件(即删除单词列表的重音等),这样我就可以使用它来使拼写检查对重音不敏感(例如在IntelliJ Idea中)。
基本上,以下是制作“附加”额外词典的步骤:
1.下载该语言的.dic文件(所有单词的列表)
1.使用grep过滤包含非ascii/可替换字符的单词
1.连续使用正则表达式替换使单词不区分重音
1.在IDE中导入附加的.dic文件(以及标准语言词典)

ih99xse1

ih99xse11#

一种实用的方法是使用Text::Unidecode

perl -C -MText::Unidecode -pe'unidecode($_)'  <<< 'à'

打印a。模块将Unicode文本转换为纯ASCII。
另一种方法:使用Unicode::Normalize分解字符(“规范化”),以便字符及其diacritical marks(组合重音)被分离成它们自己的码点,同时它们仍然形成有效的字形,然后使用简单的正则表达式删除变音符号(\p{NonspacingMark}\p{Mn})。
这两种方式都会有例外和边缘情况,但我认为它可能只是做你需要的。
对于包含特定(文字)字符的代码,需要通过utf8 pragmause utf8;或命令行标志-Mutf8告诉Perl程序源代码是UTF-8

perl -C -Mutf8 -pe's/[à]/a/g' <<< 'à'
yc0p9oo0

yc0p9oo02#

您需要添加-Mutf8来告诉Perl程序是使用UTF-8而不是ASCII编码的。

$ perl -pC -Mutf8 -e's/[à]/a/gu' <<< 'à'
a
osh3o9ms

osh3o9ms3#

简短的答案是将-Mutf8添加到命令行。
如果你不确定Perl是如何解释你在命令行上写的内容的,你可以用核心的B::perlstring()函数让它把它吐回给你,或者用B::Deparse来背离整个脚本。这将很快说明你的问题。(在这里把'à'字符括在括号里没有任何作用。)
第一个
看到你的替代品中有两个字符了吗?
然后,您可以立即看到use utf8如何修复您的问题。
第一次
您可以使用perlstring()来确保Perl正在接收您认为的输入。
第一个
您可以看到,如果没有-C,Perl将接收2个分解的字符。
根据具体情况,Perl会将字符转储为八进制代码(\340)或十六进制代码(\xE0)。注意,您总是可以将命令行中的原始unicode字符替换为转义代码版本。这是一个很好的方法,可以明确否则会产生歧义的字符。

$ perl -pC -e 's/[\xE0]/a/gu' <<< 'à'
a

如果你不想记住UTF8模式,你可以把这些选项放在PERL5OPT环境变量中,或者创建一个shell别名。
第一个
或者作为shell别名。

alias uperl='perl -C -Mutf8'

有关如何使用Swiss Army Chainsaw命令行的更多信息,请参见perlrun。
另请参阅B::Deparse

4sup72z8

4sup72z84#

下面是我实现步骤2和3的方法。
例如,这可以用在these字典中(尽管我没有在每种语言上测试它)。
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

相关问题