【问题标题】:Perl regular expression matching on large Unicode code pointsPerl 正则表达式匹配大型 Unicode 代码点
【发布时间】: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/[\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

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

这里我有一个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 `

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

【问题讨论】:

    标签: regex perl unicode encoding


    【解决方案1】:

    它不匹配,因为您在调用 Perl 时忘记了 -CSAD,并且在您的环境中没有设置 $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
    

    我确实在this answer 中多次提到过这种事情。

    【讨论】:

    • @tchrist,请通过将 -CSAD 替换为 -CSD 来更正您的答案。我没有这样做的编辑权力。
    • @HansDeragon 完成。
    【解决方案2】:

    使用use utf8;,您告诉 Perl 您的源代码是 UTF-8。这是无用的(尽管无害),因为您已将源代码限制为 ASCII。

    使用/u,您告诉Perl 使用\s\d\w 的Unicode 定义。这是无用的(尽管无害),因为您不使用任何这些模式。

    您没有解码您的输入,因此您的输入仅由字节组成,因此您班级中的大多数字符(例如\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
    

    【讨论】:

    • 我讨厌必须弄清楚如何在 shell 中引用东西。我通常只选择\x27 技巧。
    • 我刚做了''\'' 不假思索,买是的,'\x27 是个好主意。
    • 我认为你的意思是“需要解码你的输入”,然后可能还“需要编码你的输出”。
    • @tchirst,错字已修复。已添加。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 2011-08-04
    相关资源
    最近更新 更多