在我的语言环境中(et_EE)[a-z]
表示:
abcdefghijklmnopqrsšz
因此,不包括6个ASCII字符(tuvwxy
)和一个来自爱沙尼亚字母(ž
)。我看到很多模块仍在使用像
/\A[0-9A-Z_a-z]+\z/
对我来说,定义ASCII字母数字字符范围似乎是错误的方法,我认为它应该替换为:
/\A\p{PosixAlnum}+\z/
第一个仍然被认为是惯用的方式吗?或接受解决方案?还是个bug?
或者最后一个警告?
答案 0 :(得分:8)
回到旧的Perl 3.0天,一切都是ASCII,Perl反映了这一点。 \w
与[0-9A-Z_a-z]
的含义相同。而且,我们喜欢它!
但是,Perl不再绑定到ASCII。我刚才停止使用[a-z]
,因为当我写的程序不适用于不是英语的语言时,我被大吼大叫。作为一个美国人,你一定想到了我的惊喜,发现这个世界上有数千名不会说英语的人至少。
无论如何,Perl有更好的处理方式[0-9A-Z_a-z]
。您可以使用[[:alnum:]]
集,或只使用\w
来做正确的事情。如果您只能使用小写字符,则可以使用[[:lower:]]
代替[a-z]
(假设使用英语类型的语言)。 (即使在EBCDIC平台上,Perl也会花一些时间来获得[a-z]意味着26个字符a,b,c,... z。)
如果您只需要指定ASCII,则可以添加/a
限定符。如果您指的是特定于语言环境,则应在“使用语言环境”的词法范围内编译正则表达式。 (避免使用/ l修饰符,因为它仅适用于正则表达式模式,而不包含任何其他内容。例如在's / [[:lower:]] / \ U $& / lg'中,模式使用locale编译但是\ U不是。这可能应该被认为是Perl中的一个错误,但它是当前工作的方式。/ l修饰符实际上只用于内部簿记,不应该直接输入。)实际上,最好在输入到程序时转换您的语言环境数据,并在输出时将其转换回来,同时在内部使用Unicode。如果你的语言环境是新一代的UTF-8,那么5.16中的一个新功能“使用locale”:not_characters“'可以让你的语言环境的其他部分在Perl中无缝地工作。
$word =~ /^[[:alnum:]]+$/ # $word contains only Posix alphanumeric characters.
$word =~ /^[[:alnum:]]+$/a # $word contains only ASCII alphanumeric characters.
{ use locale;
$word =~ /^[[:alnum:]]+$/;# $word contains only alphanum characters for your locale
}
现在,这是一个错误吗?如果程序没有按预期工作,那么这是一个简单明了的错误。如果你真的想要ASCII序列[a-z]
,那么程序员应该使用[[:lower:]]
和/a
限定符。如果您想要所有可能的小写字符,包括其他语言的字符,您只需使用[[:lower:]]
。
答案 1 :(得分:5)
您遇到的问题不在于POSIX字符类本身,而是因为这些类依赖于语言环境。例如,正则表达式(7)说:
在括号表达式中,“[:”和“:]”中包含的字符类的名称代表属于该类的所有字符的列表...这些代表wctype中定义的字符类(3 )。 区域设置可能会提供其他区域。
重点是我的,但手册页明确指出角色类依赖于语言环境。此外,wctype(3)说:
wctype()的行为取决于当前语言环境的LC_CTYPE类别。
换句话说,如果您的语言环境错误地定义了一个字符类,那么它应该是针对特定语言环境提交的错误。另一方面,如果字符类只是以你不期望的方式定义字符集,那么它可能不是一个bug;它可能只是一个需要编码的问题。
字符类是定义集的快捷方式。您当然不限于您的语言环境的预定义集,并且您可以自由使用perlre(1)定义的Unicode字符集,或者只是提供明确创建的集合,如果它提供更高的准确性。
你已经知道这一点,所以我不是想要迂腐。我只是指出,如果你不能或不会修复语言环境(这是问题的根源)那么你应该使用一个显式集,就像你所做的那样。
便利类只有在适合您的用例时才方便。如果没有,就把它抛到一边!
答案 2 :(得分:0)
对于 awk,也许在字母表上强制使用八进制代码应该可以避免 awk/poxix/locales 中的不一致
类似的东西
/[\060-\071 # 0-9
\101-\132 # A-Z
\141-\172]/ # a-z
如果你想把它们变成字符串常量,也许把反斜杠加倍,以确保解析器/正则表达式引擎不会变得太聪明并将 "\101" 预转换为 A,并为其“尊重”可能不是您想要的区域设置提供机会。
<块引用>"\\101"