【发布时间】:2013-02-03 06:12:13
【问题描述】:
从我之前的问题Why under locale-pragma word characters do not match? 和How to change nested quotes 我了解到,在处理 UTF-8 数据时,您不能将 \w 视为 word-char,您必须使用 Unicode 字符属性 \p{Word}。现在我发现零宽度字边界\b 也不适用于 UTF-8(启用了语言环境),但我在 Unicode 字符属性中没有找到任何等效项。我想我可以自己构造它:(?<=\P{Word})(\p{Word}+)(?=\P{Word}),它应该相当于\b(\w+)\b。
在下面的测试脚本中,我有两个数组来测试两个不同的正则表达式。第一个基于\b 在未启用区域设置时工作正常。为了让它也适用于语言环境,我编写了另一个带有模拟边界(?=\P{Word}) 的版本,但它没有按我的预期工作(我也在脚本中显示了预期的结果)。
您知道什么是错误的吗?如何让模拟的正则表达式首先使用 ASCII(或没有语言环境)?
#!/usr/bin/perl
use 5.010;
use utf8::all;
use locale; # et_EE.UTF-8 in my case
$| = 1;
my @test_boundary = ( # EXPECTED RESULT:
'"abc def"', # '«abc def»'
'"abc "d e f" ghi"', # '«abc «d e f» ghi»'
'"abc "d e f""', # '«abc «d e f»»'
'"abc "d e f"', # '«abc "d e f»'
'"abc "d" "e" f"', # '«abc «d» «e» f»'
# below won't work with \b when locale enabled
'"100 Естонiï"', # '«100 Естонiï»'
'"äöõ "ä õ ü" ï"', # '«äöõ «ä õ ü» ï»'
'"äöõ "ä õ ü""', # '«äöõ «ä õ ü»»'
'"äöõ "ä õ ü"', # '«äöõ «ä õ ü»'
'"äöõ "ä" "õ" ï"', # '«äöõ «ä» «õ» ï»'
);
my @test_emulate = ( # EXPECTED RESULT:
'"100 Естонiï"', # '«100 Естонiï»'
'"äöõ "ä õ ü" ï"', # '«äöõ «ä õ ü» ï»'
'"äöõ "ä õ ü""', # '«äöõ «ä õ ü»»'
'"äöõ "ä õ ü"', # '«äöõ "ä õ ü»'
'"äöõ "ä" "õ" ï"', # '«äöõ «ä» «õ» ï»'
);
say "BOUNDARY";
for my $sentence ( @test_boundary ) {
my $quote_count = ( $sentence =~ tr/"/"/ );
for ( my $i = 0 ; $i <= $quote_count ; $i += 2 ) {
$sentence =~ s/
"( # first qoute, start capture
[\p{Word}\.]+? # suva word-char
.*?\b[\.,?!»]*? # any char followed boundary + opt. punctuation
)" # stop capture, ending quote
/«$1»/xg; # change to fancy
}
say $sentence;
}
say "EMULATE";
for my $sentence ( @test_emulate ) {
my $quote_count = ( $sentence =~ tr/"/"/ );
for ( my $i = 0 ; $i <= $quote_count ; $i += 2 ) {
$sentence =~ s/
"( # first qoute, start capture
[\p{Word}\.]+? # at least one word-char or point
.*?(?=\P{Word}) # any char followed boundary
[\.,?!»]*? # optional punctuation
)" # stop capture, ending quote
/«$1»/gx; # change to fancy
}
say $sentence;
}
【问题讨论】:
-
首先,您误会了:
\w和\p{word}在定义上是相同的。但第二,拜托,拜托,拜托不要使用use localepragma。它是破碎的、不可靠的、不可预测的,并且是一种令人难以忍受的痛苦——正如你似乎已经发现的那样。您应该使用Unicode::Collate::Locale模块。你可能也不应该使用use utf8:all,而是做你想做的特定事情。 -
@tchrist:
\w和\p{Word}可能定义相同,但在use locale下它们的行为不同。当然,当我现在有其他方式时,我不会使用语言环境。use utf8::all很好地满足了我的需求,这是表达我意图的干净方式。如果 utf8::all 有一些不足,也许你可以指出作者? -
你不知道
utf8:all做什么或不做什么,这正是问题所在——我注意到,这个问题不能通过添加东西来解决。你得到什么级别的utf8警告?没有或警告或致命的?那么这三个子类型,nonchar 和 surrogates 以及 non_unicode 呢?这些东西应该在代码中明确显示,以便人们可以看到它们是什么。然后是在输入端渲染成 NFD,在输出端渲染成 NFC 的问题;这样做吗? -
@tchrist:我对
utf8::all内部结构的理解比DBI、Unicode::Collate::Locale或Perl 核心内部结构要好得多,但这并不能阻止我在有限的范围内尽可能地使用它们。例如,我从不担心标准化。当我有一天,我会更深入地挖掘。这对我来说是正常的抽象级别 - 当它们没有足够的意义但按预期工作时,不要担心底层细节。在utf8::all出现的时候,我自己也已经把大部分图片放在一起了。但是使用它我说:你们都可以使用一些“轮子”。我想念它在核心
标签: regex perl unicode utf-8 locale