如何用代码点而不是字素代替Perl 6中的字符串?

时间:2018-09-10 13:46:08

标签: regex unicode perl6

我需要使用Perl 6从字符串中删除变音符号。我尝试这样做:

my $hum = 'חוּם';
$ahm.subst(/<-[\c[HEBREW LETTER ALEF] .. \c[HEBREW LETTER TAV]]>/, '', :g);

我正在尝试删除不在HEBREW LETTER ALEF(א)和HEBREW LETTER TAV(ת)之间的所有字符。我希望下面的代码返回“חום”,但是它返回“חם”。

我猜发生的事情是,默认情况下,Perl 6由字素起作用,将ּ视为一个字素,然后将其全部删除。用字素工作通常是明智的,但是在我的情况下,我需要它通过代码点来工作。

我试图找到一个副词,该副词可以使它按代码点运行,但找不到。也许Perl 6中还有一种使用Unicode属性排除变音符号或仅包含字母的方法,但是我也找不到。

谢谢!

2 个答案:

答案 0 :(得分:9)

我的regex-fu很弱,所以我会选择一种不太神奇的解决方案。

首先,您可以通过samemark删除所有标记:

'חוּם'.samemark('a')

第二,您可以通过.NFD分解字素并在各个代码点上进行操作-例如仅保留具有属性Grapheme_Base的值-然后重新组成字符串:

Uni.new('חוּם'.NFD.grep(*.uniprop('Grapheme_Base'))).Str

在混合字符串的情况下,仅从希伯来语字符中剥离标记可能看起来像这样:

$str.subst(:g, /<:Script<Hebrew>>+/, *.Str.samemark('a'));

答案 1 :(得分:3)

这是一种简单的方法:

my $hum = 'חוּם';
my $min = "\c[HEBREW LETTER ALEF]".ord;
my $max = "\c[HEBREW LETTER TAV]".ord;
my @ords;
for $hum.ords {
    @ords.push($_) if $min ≤ $_ ≤ $max; 
}
say join('', @ords.map: { .chr });

输出

חום
相关问题