Perl 中的正则表达式不匹配 Unicode 字符串

Regex in Perl not matching a Unicode String

我正在尝试使用 Perl 正则表达式匹配 Unicode 字符串。如果我将字符串输出到 STDOUT,该字符串似乎毫发无损地到达了我的模块:“Asuncion, Distrito Capital de Paraguay, Región Oriental, Paraguay.”

但是,它在 Regex 中不匹配。奇怪的是,如果我将脚本的输出复制到一个变量中并对其进行评估,那么 does 在同一个正则表达式中匹配:

use v5.12;
use utf8;

my $placeString = $main::FORM{'placeString'}; # Coming from a different module.
say STDOUT $placeString;

utf8::upgrade($placeString); # Using this or removing this seems to make no difference.

# If I manually copy the output of STDOUT (above) in BASH and set the string, it works:
$placeString2 = "Asuncion, Distrito Capital de Paraguay, Región Oriental, Paraguay"; 

if ($placeString =~ /^([\w\s\,\.\-\']+)$/) {
    # This is evaluated as false.
    say STDERR "Accepted placename.";
}


if ($placeString2 =~ /^([\w\s\,\.\-\']+)$/) {
    # This is evaluated as true.
    say STDERR "Accepted placename.";
}

However, it won't match in Regex.

从评论中可以清楚地看出该值是 UTF-8 编码的字符串。您需要在进行匹配之前对值进行解码:

use Encode qw(decode_utf8);
$placeString = decode_utf8($placeString);

$placeString2 是一串解码后的文本。您也可以将其称为一串 Unicode 代码点,因为它的每个字符都是这样。

52.65.67.69.F3.6E      Unicode Code Points for "Región".

这些 UCP 中的每一个都适合一个字节,但情况并非总是如此。

49.2665.53.4F          Unicode Code Points for "I♥SO".

$placeString 是一串编码文本。它的每个字符都是一个字节。

52.65.67.69.C3.B3.6E   "Región" encoded using UTF-8.
49.E2.99.A5.53.4F      "I♥SO" encoded using UTF-8.

解码输入,编码输出。

\w\s 期望匹配 Unicode 代码点。但是正如我们已经确定的那样,$::FORM{placeString} 的值是这些代码点的编码。您需要对其进行解码。

my $placeString = $::FORM{placeString};
utf8::decode($placeString)
   or warn(...);

use Encode qw( decode_utf8 );

my $placeString = decode_utf8($::FORM{placeString});

如果字符串来自文件句柄,则最好为句柄添加解码层。