【问题标题】:How can I substitute in strings in Perl 6 by codepoint rather than by grapheme?如何在 Perl 6 中用代码点而不是字形替换字符串?
【发布时间】:2019-02-14 23:19:44
【问题描述】:

我需要使用 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 属性来排除变音符号,或者只包含字母,但我也找不到。

谢谢!

【问题讨论】:

    标签: regex unicode raku


    【解决方案1】:

    我的正则表达式很弱,所以我会选择一个不那么神奇的解决方案。

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

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

    其次,您可以通过.NFD 分解字素并对单个代码点进行操作——例如只保留属性Grapheme_Base 的值——然后重新组合字符串:

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

    在混合字符串的情况下,从希伯来字符中剥离标记只能如下所示:

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

    【讨论】:

    • 在实际应用程序中,转换应仅限于希伯来语脚本序列以避免负面影响。
    【解决方案2】:

    这是一个简单的方法:

    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 });
    

    输出

    חום
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-06
      • 2014-12-03
      • 2014-10-06
      • 1970-01-01
      • 1970-01-01
      • 2019-02-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多