Perl 正则表达式匹配大型 Unicode 代码点
Posted
技术标签:
【中文标题】Perl 正则表达式匹配大型 Unicode 代码点【英文标题】:Perl regular expression matching on large Unicode code points 【发布时间】:2012-09-22 17:52:00 【问题描述】:我正在尝试用单引号或双引号替换各种字符。
这是我的测试文件:
# Replace all with double quotes
" fullwidth
“ left
” right
„ low
" normal
# Replace all with single quotes
' normal
‘ left
’ right
‚ low
‛ reverse
` backtick
我正在尝试这样做......
perl -Mutf8 -pi -e "s/[\x2018\x201A\x201B\xFF07\x2019\x60]/'/ug" test.txt
perl -Mutf8 -pi -e 's/[\xFF02\x201C\x201D\x201E]/"/ug' text.txt
但只有反引号字符被正确替换。我认为这与其他代码点太大有关,但我找不到任何关于此的文档。
这里我有一个one-liner,它转储了 Unicode 代码点,以验证它们是否与我的正则表达式匹配。
$ awk -F\ 'print $1' test.txt | \
perl -C7 -ne 'for(split(//))print sprintf("U+%04X", ord)." ".$_."\n"'
U+FF02 "
U+201C “
U+201D ”
U+201E „
U+0022 "
U+0027 '
U+2018 ‘
U+2019 ’
U+201A ‚
U+201B ‛
U+0060 `
为什么我的正则表达式不匹配?
【问题讨论】:
【参考方案1】:它不匹配,因为您在调用 Perl 时忘记了 -CSAD
,并且在您的环境中没有设置 $PERL_UNICODE
。您只是说-Mutf8
来宣布您的源代码采用该编码。这不会影响您的 I/O。
你需要:
$ perl -CSAD -pi.orig -e "s/[\x2018\x201A\x201B\xFF07\x2019\x60]/'/g" test.txt
我确实在this answer 中多次提到过这种事情。
【讨论】:
@tchrist,请通过将 -CSAD 替换为 -CSD 来更正您的答案。我没有这样做的编辑权力。 @HansDeragon 完成。【参考方案2】:使用use utf8;
,您告诉 Perl 您的源代码是 UTF-8。这是无用的(尽管无害),因为您已将源代码限制为 ASCII。
使用/u
,您告诉Perl 使用\s
、\d
、\w
的Unicode 定义。这是无用的(尽管无害),因为您不使用任何这些模式。
您没有解码您的输入,因此您的输入仅由字节组成,因此您班级中的大多数字符(例如\x2018
)不可能匹配任何内容。你需要解码你的输入(当然,编码你的输出)。使用-CSD
可能会做到这一点。
perl -CSD -i -pe'
s/[\x2018\x201A\x201B\xFF07\x2019\x60]/\x27/g;
s/[\xFF02\x201C\x201D\x201E]/"/g;
' text.txt
【讨论】:
我讨厌必须弄清楚如何在 shell 中引用东西。我通常只选择\x27
技巧。
我刚做了'
⇒ '\''
不假思索,买是的,'
⇒ \x27
是个好主意。
我认为你的意思是“需要解码你的输入”,然后可能还“需要编码你的输出”。
@tchirst,错字已修复。已添加。以上是关于Perl 正则表达式匹配大型 Unicode 代码点的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Perl 中仅匹配 Unicode 字符串中的完全组合字符?