如何获取具有特定属性的所有Unicode字符列表?

7

如何获取具有特定属性的字符列表,而不需要循环遍历Unicode字符的整个范围?具体来说,我希望获得所有数字字符(即与/\d/匹配的字符)的列表。我已经查看了Unicode::UCD,它对于确定给定字符的属性非常有用,但似乎没有一种方法可以从中获取具有某个属性的字符列表。

4个回答

6
每个类别的Unicode字符列表在编译Perl时从Unicode规范中生成,通常存储在/usr/lib/perl-YOURPERLVERSION/unicore/lib/gc_sc/中。例如,与IsDigit(又名\d)匹配的Unicode字符范围列表存储在文件/usr/lib/perl-YOURPERLVERSION/unicore/lib/gc_sc/Digit.pl中。

谢谢,这几乎就是我要找的。我仍然需要循环遍历它们来构建列表,但至少不会花费太长时间。 - Chas. Owens

1
比起 unicore/lib/gc_sc/Digit.plunicore/To/Digit.pl 更好。它直接将 Unicode 数字字符(实际上是它们的偏移量)映射到它们的数值。这意味着不需要:
use Unicode::Digits qw/digit_to_int/;

my @digits;
for (split "\n", require "unicore/lib/gc_sc/Digit.pl") {
    my ($s, $e) = map hex, split;
    for (my $ord = $s; $ord <= $e; $ord++) {
        my $chr = chr $ord;
        push @{$digits[digits_to_int $chr]}, $chr;
    }
}

for my $i (0 .. 9) {
    my $re = join '', "[", @{$digits[$i]}, "]";
    $digits[$i] = qr/$re/;
}

我可以说:

my @digits;
for (split "\n", require "unicore/To/Digit.pl") {
    my ($ord, $val) = split;
    my $chr = chr hex $ord;
    push @{$digits[$val]}, $chr;
}

for my $i (0 .. 9) {
    my $re = join '', "[", @{$digits[$i]}, "]";
    $digits[$i] = qr/$re/;
}

或者更好的是:

my @digits;
for (split "\n", require "unicore/To/Digit.pl") {
    my ($ord, $val) = split;
    $digits[$val] .= "\\x{$ord}";
}
@digits = map { qr/[$_]/ } @digits;

0

/\d/ 匹配哪些字符完全取决于您的正则表达式实现(尽管标准的0-9是保证的)。在 Perl 的情况下,使用的 perl locale 定义了哪些字符被认为是字母和数字。


Perl在运行正则表达式引擎之前会将字符串转换为utf8。Perl语言环境影响的唯一事项是原始字节串如何转换为utf8。一旦字符串处于utf8状态,Perl将始终使用相同的IsDigit定义,与语言环境无关。 - tetromino

0

没有办法在不迭代所有字符的情况下完成这个操作。 (如果您创建一个包含所有字符的巨大字符串并使用正则表达式,您仍然必须至少执行一次循环以创建该字符串)。


愉快地,Perl 构建过程的一部分会在一个 lib 目录下的 unicore 文件夹中创建一组文件,这些文件已经为你完成了很多工作。我不知道它们是否官方的,我向 Perl 5 Porters 列表提出了一个问题,以确定是否安全使用它们。 - Chas. Owens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接