如何使用Unicode字符属性时模仿单词边界?(How to emulate word bounda

2019-07-20 03:14发布

从我前面的问题,为什么在语言环境的编译单词字符不匹配? 而如何改变嵌套引用我了解到,使用UTF-8的数据处理时,你不能相信\w作为文字字符,你必须使用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;
}

Answer 1:

由于位置之后的字符\b或者是一些标点符号或" (为了安全起见,请仔细检查\p{Word}不符合任何人的),它落入的情况下\b\W 。因此,我们可以模拟\b有:

(?<=\p{Word})

我不熟悉Perl,但是从我这里测试 ,似乎\w (和\b )也很好地工作时,编码设置为UTF-8。

$sentence =~ s/
  "(
    [\w\.]+?
    .*?\b[\.,?!»]*?
  )"
  /«$1»/xg;

如果您将学习Perl 5.14及以上的,可以设置的字符集与为Unicode u标志。


你可以使用这个总体战略,构建对应于字符类的边界。 (怎么样\b字边界的定义是基于定义\w )。

C是字符类。 我们想定义一个基于字符类C.边界

下面的建设将效仿边界在面前的时候,你知道当前字符属于C字符类(等效于(\b\w)

(?<!C)C

或后面(相当于\w\b ):

C(?!C)

为什么负面环视? 因为正环视(与互补字符类)也将断言,必须有一个字符超前/落后(断言宽度超前/落后至少1)。 负环视将允许字符串的开始/结束的情况下,无需编写繁琐的正则表达式。


对于\B\w仿真:

(?<=C)C

并且类似地\w\B

C(?=C)

\B是直接相反\b ,因此,我们可以只翻转正/负环视模拟的效果。 这也有道理 - 非边界只能形成时有更多的字符前面/后面。


其他仿真(让c是补体字符类的C ):

  • \b\W(?<=C)c
  • \W\bc(?=C)
  • \B\W(?<!C)c
  • \W\Bc(?!C)

对于独立边界的仿真(相当于\b ):

(?:(?<!C)(?=C)|(?<=C)(?!C))

和独立的非边界(相当于\B ):

(?:(?<!C)(?!C)|(?<=C)(?=C))


Answer 2:

您应该使用负lookarounds:

(?<!\p{Word})(\p{Word}+)(?!\p{Word})

正lookarounds在开始或结束的字符串失败,因为他们需要一个非单词字符存在。 负lookarounds在这两种情况下工作。



文章来源: How to emulate word boundary when using unicode character properties?