在大型Unicode代码点上进行Perl正则表达式匹配

Dav*_*han 5 regex unicode perl encoding

我试图用单引号或双引号替换各种字符.

这是我的测试文件:

# Replace all with double quotes
? fullwidth
“ left
” right
„ low
" normal

# Replace all with single quotes
' normal
‘ left
’ right
‚ low
? reverse
` backtick
Run Code Online (Sandbox Code Playgroud)

我正试图这样做......

perl -Mutf8 -pi -e "s/[\x{2018}\x{201A}\x{201B}\x{FF07}\x{2019}\x{60}]/'/ug" test.txt
perl -Mutf8 -pi -e 's/[\x{FF02}\x{201C}\x{201D}\x{201E}]/"/ug' text.txt
Run Code Online (Sandbox Code Playgroud)

但只有反引号字符才能被正确替换.我认为它与其他代码点太大有关,但我找不到任何关于此的文档.

在这里,我有一个单行代码转储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 `
Run Code Online (Sandbox Code Playgroud)

为什么我的正则表达式不匹配?

tch*_*ist 19

它不匹配,因为您忘记了-CSAD 对Perl的调用,并且没有$PERL_UNICODE在您的环境中设置.您只是-Mutf8声明您的源代码采用该编码.这不会影响您的I/O.

你需要:

$ perl -CSAD -pi.orig -e "s/[\x{2018}\x{201A}\x{201B}\x{FF07}\x{2019}\x{60}]/'/g" test.txt
Run Code Online (Sandbox Code Playgroud)

我在这个答案中确实提过了几次这样的事情.


ike*_*ami 7

有了use utf8;,你告诉Perl你的源代码是UTF-8.由于您已将源代码限制为ASCII,因此无用(尽管无害).

有了/u,你告诉Perl来使用的Unicode的定义\s,\d,\w.这是无用的(虽然无害),因为你不使用任何这些模式.

你没有解码你的输入,所以你的输入只包含字节,所以你的类中的大多数字符(例如\x{2018})都不可能匹配任何东西.您需要解码输入(当然,还要对输出进行编码).使用-CSD可能会这样做.

perl -CSD -i -pe'
   s/[\x{2018}\x{201A}\x{201B}\x{FF07}\x{2019}\x{60}]/\x27/g;
   s/[\x{FF02}\x{201C}\x{201D}\x{201E}]/"/g;
' text.txt
Run Code Online (Sandbox Code Playgroud)