我正在寻找一种仅匹配 Unicode 字符串中完全组成的字符的方法。
是否[:print:]
依赖于包含此字符类的任何正则表达式实现中的语言环境?例如,它会匹配日文字符“あ”,因为它不是控制字符,还是[:print:]
总是 ASCII 码 0x20 到 0x7E?
是否有任何字符类(包括 Perl RE)可用于匹配控制字符以外的任何内容?如果[:print:]
仅包含 ASCII 范围内的字符,我会假设[:cntrl:]
也包含。
我正在寻找一种仅匹配 Unicode 字符串中完全组成的字符的方法。
是否[:print:]
依赖于包含此字符类的任何正则表达式实现中的语言环境?例如,它会匹配日文字符“あ”,因为它不是控制字符,还是[:print:]
总是 ASCII 码 0x20 到 0x7E?
是否有任何字符类(包括 Perl RE)可用于匹配控制字符以外的任何内容?如果[:print:]
仅包含 ASCII 范围内的字符,我会假设[:cntrl:]
也包含。
echo あ| perl -nle 'BEGIN{binmode STDIN,":utf8"} print"[$_]"; print /[[:print:]]/ ? "YES" : "NO"'
这主要是有效的,尽管它会生成一个关于宽字符的警告。但它给了你一个想法:你必须确保你正在处理一个真正的 unicode 字符串(检查 utf8::is_utf8)。或者只是检查perlunicode - 整个主题仍然让我头晕目眩。
我认为您不需要或不需要语言环境,而是Unicode。如果您已解码文本字符串,\w
将匹配任何语言中的单词字符,\d
不仅匹配0..9
每个 Unicode 数字等。在正则表达式中,您可以使用\p{PropertyName}
. 对你来说特别有趣的可能是\p{Print}
。这是所有可用 Unicode 字符属性的列表。
我写了一篇关于 Unicode 和 Perl 的基础知识和精妙之处的文章,它应该让你很好地了解 perl 会将你的字符串识别为一个字符序列,而不仅仅是一个字节序列。
更新:使用 Unicode,您不会获得依赖于语言的行为,而是无论语言如何,都是合理的默认值。这可能是您想要的,也可能不是您想要的,但是为了区分可打印/控制字符,我不明白为什么您需要依赖语言的行为。
\X
匹配一个完全组合的字符(序列)。证明:
#!/usr/bin/env perl
use 5.010;
use utf8;
use Encode qw(encode_utf8);
for my $string (qw(あ ご ご), "\x{3099}") {
say encode_utf8 sprintf "%s $string", $string =~ /\A \X \z/msx ? 'ok' : 'nok';
}
测试数据是:一个普通字符、一个预组合字符、一个组合字符序列和一个组合字符(它本身“不算数”,对Unicode第3章的简化)。
替换\X
为[[:print:]]
看到 Tanktalus 的答案在最后两种情况下产生错误匹配。
是的,这些表达式取决于语言环境。
您始终可以使用字符类[^[:cntrl:]]
来匹配非控制字符。