正则表达式匹配具有特定变音符号的字符

时间:2016-02-13 02:58:59

标签: regex perl unicode diacritics

正则表达式中是否有任何方法可以为具有特定变音符号的字符指定匹配?让我们说一个重要的口音。要做到这一点很长的路要走到Wikipedia page on the grave accent,复制它显示的所有字符,然后用它们制作一个字符类:

/[àầằèềḕìǹòồṑùǜừẁỳ]/i

这很乏味。我希望有一个像\p{hasGraveAccent}这样的Unicode属性,但我找不到那样的东西。搜索解决方案只会出现人们试图匹配字符的问题,而忽略了变音符号,这涉及执行某种规范化,这不是我想要的。

2 个答案:

答案 0 :(得分:1)

可能存在一些限制。

#!perl

use strict;
use warnings;

use Encode;
use Unicode::Normalize;
use charnames qw();
use utf8;  # source is utf-8

binmode(STDOUT, ":utf8"); # print in utf-8

my $utf8_string = 'xàaâèaêòͤ';

my $nfd_string = NFD($utf8_string); # decompose

my @chars_with_grave = $nfd_string =~
  m/
    (
      \p{L}           # one letter
      \p{M}*          # 0 or more marks
      \N{COMBINING GRAVE ACCENT}
      \p{M}*          # 0 or more marks
    )
  /xmsg;

print join(', ',@chars_with_grave), "\n";

打印

$ perl utf_match_grave.pl 
à, è, òͤ

注意:编辑区域中的字符正确显示为合并,但stackoverflow会将它们错误地分开。

它需要一个字母作为基本字符。更改其他基本字符的正则表达式。标记\p{M}可能不是你想要的,应该改进。

答案 1 :(得分:0)

这是一个棘手的问题,但它是可能的。首先,您必须将unicode字符串规范化为4种形式之一。关于规范化的信息是here,具有不同规范化的字符示例的映射是here,并且规范化字符的良好图表是here。从本质上讲,规范化只是确保在处理变音符号时所有字符都采用相同的格式。 Golang对此有很大的支持,并且大多数语言都应该包含用于执行此操作的库。

因此,对于我的示例,将字符串转换为“Normalization Form D”(NFD)和utf32,因此所有unicode字符都是4字节的代码点。

严重重音的所有变音字符在字符旁边都有0x0300。因此,您可以在....\x00\x00\x03\x00的ascii模式(非unicode模式)中进行正则表达式搜索。从那里你必须提取它所在的符文位置。这可以通过不同的方法来完成,具体取决于你使用的编码。

因此,如果你登上4的分区,你就会知道它是一个有效的角色。

除此之外,没有正式的perl字符分组可以做到这一点。

以Perl代码为例:

use Encode;
use Unicode::Normalize;

$StartUTF8='xàaâèaê';
$PerlEncoded=decode('utf8', $StartUTF8);
$PerlNormalized=NFD($PerlEncoded); 
$UTF32Normalized=encode('utf32', $PerlNormalized);

while($UTF32Normalized =~ /(....\x00\x00\x03\x00)/gs) {
    $Pos=pos($UTF32Normalized)-8;
    if($Pos%4==0) {
        print("$Pos\n");
    }
}

但是在这一点上,您可能只是对字符进行for循环: - \

我也试过匹配而不需要使用// c进行位置测试,但由于某种原因它不起作用。

/^(?:....)*?(....\x00\x00\x03\x00)/gcs