com*_*orm 7 regex sorting perl
我遇到了一些奇怪的Perl行为:在regexp中使用Posix字符类完全改变了结果字符串的排序顺序.
这是我的测试程序:
sub namecmp($a,$b) {
$a=~/([:alpha:]*)/;
# $a=~/([a-z]*)/;
$aword= $1;
$b=~/([:alpha:]*)/;
# $b=~/([a-z]*)/;
$bword= $1;
return $aword cmp $bword;
};
$_= <>;
@names= sort namecmp split;
print join(" ", @names), "\n";
Run Code Online (Sandbox Code Playgroud)
如果使用[az]更改为注释掉的正则表达式,则会获得正常的词典排序顺序.但是,Posix [:alpha:]字符类会产生一些怪异的排序顺序,如下所示:
$test_normal
aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cbb
aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cbb
$test_posix
aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cbb
baa bab bac bba bbb bbc bca bcb bcc caa cbb aba abb abc aca acb acc aab aac aaa
Run Code Online (Sandbox Code Playgroud)
我最好的猜测是Posix角色类正在激活一些我从未听说过并且没有要求的语言环境.我想逻辑反应,"大夫,大夫,我这做的时候疼这个!" 是,"好了,不要做那个的话!".
但是,谁能告诉我这里发生了什么,为什么?我使用的是perl 5.10,但我相信它也可以在perl 5.8下运行.
Gre*_*ill 13
字符类[:alpha:]表示Perl正则表达式中的字母字符,但方括号并不表示它们在正则表达式中通常执行的操作.所以你需要:
$a=~/([[:alpha:]]*)/;
Run Code Online (Sandbox Code Playgroud)
这在perlre中提到:
POSIX字符类语法
Run Code Online (Sandbox Code Playgroud)[:class:]也可以.需要注意的是,
[和]括号内的文字; 它们必须始终在字符类表达式中使用.
# this is correct:
$string =~ /[[:alpha:]]/;
# this is not, and will generate a warning:
$string =~ /[:alpha:]/;
Run Code Online (Sandbox Code Playgroud)
你所写的不是Perl的任何想象力.因为你已经关闭,你可以逃脱它warnings.如果您使用过警告,perl会告诉您
POSIX syntax [: :] belongs inside character classes in regex; marked by <-- HERE
in m/([:alpha:] <-- HERE *)/ at j.pl line 4.
POSIX syntax [: :] belongs inside character classes in regex; marked by <-- HERE
in m/([:alpha:] <-- HERE *)/ at j.pl line 8.
设想!
现在,perl也会告诉你:
Illegal character in prototype for main::namecmp : $a,$b at j.pl line 3.
因为,Perl不是C. Perl没有你似乎试图使用的那种函数原型.
这次在Perl中编写完全相同的功能的更好方法是:
use warnings; use strict;
sub namecmp {
my ($aword) = $a =~ /([[:alpha:]]*)/;
my ($bword) = $b =~ /([[:alpha:]]*)/;
return $aword cmp $bword;
}
print join(' ', sort namecmp split ' ', scalar <>), "\n";
Run Code Online (Sandbox Code Playgroud)
因为Perl不支持此表单中的POSIX字符类.(使用[[:alpha:]].请参阅@ Greg的回答)
所以
[:alpha:]
Run Code Online (Sandbox Code Playgroud)
被解释为由字符" a"," h"," l"," p"和" :" 组成的字符类.
现在,对于[ahlp:] 在开头没有任何内容的字符串(因为*),例如" baa"匹配将返回一个空字符串.当然,空字符串当然比任何其他字符串小,所以它们将在开头排列.