我今天遇到了这个Perl构造:
@foo = split("\n", $bar);
适用于将大型字符串拆分为UNIX类型行结尾的行数组,但为Windows留下尾随\ r \ n。所以我把它改成了:
@foo = split("\r?\n", $bar);
将字符串按行拆分,不留下尾随\ r \ n(在ActivePerl 5.8下测试)。然后有人向我指出,这应该是:
@foo = split(/\r?\n/, $bar);
那么为什么第二种变体会起作用呢?双引号意味着评估内容,这就是为什么\ r和\ n实际上被视为CR和LF,但是?被视为正则表达式字符而不是文字问号。
正则表达式周围的斜杠是split()的可选项吗?是否假设该函数的第一个参数是正则表达式?
答案 0 :(得分:6)
斜杠只是正则表达式的标准分隔符(您可以使用其他分隔符),它们像双引号一样评估特殊字符和转义序列。
编辑:我拍摄得太快,正如Manni在评论中解释的那样。我会尝试更长的解释:
通常,Perl中匹配的正则表达式以m开头,然后将正则表达式主体括在某个分隔符中。匹配正则表达式的标准分隔符是斜杠,如果使用斜杠作为分隔符,则可以省略前导m
:
m/\r?\n/
m"\r?\n"
m$\r?\n$
/\r?\n/
这些都是一样的,它们被称为“正则表达式文字”。如果使用单引号,则不会对转义序列进行求值。
此时,您的第一次尝试(双引号中的正则表达式但没有前导m
)似乎很奇怪,但正如Arnshea所解释的那样,split
是一个特殊情况,因为它不仅接受正则表达式作为文字,而且接受字符串。
答案 1 :(得分:6)
您可以将正则表达式作为字符串或正则表达式文字传递。所以将它作为双引号字符串传递就可以了。
您还可以使用标准/ regex /
以外的字符分隔正则表达式文字答案 2 :(得分:5)
是的,split总是采用正则表达式(包含单个空格特殊情况的字符串除外)。如果你给它一个字符串,那将用作正则表达式。 =〜(例如$ foo =〜“pattern”)也会发生同样的事情。无论是否使用//.
,正则表达式元字符都将被视为符号这就是为什么始终使用//是一个好主意,强调它有时不是文字字符串或有时是正则表达式,所以你不小心尝试拆分(“|”,“a | b | c“)有一天。
答案 3 :(得分:1)
use Modern::Perl;
use Benchmark qw'cmpthese';
# set up some test data
my $bar = join "\n", 'a'..'z';
my $qr = qr/\r?\n/;
my $str = "\r?\n";
my $qq = qq/\r?\n/;
my %test = (
' //' => sub{ split( /\r?\n/, $bar ); },
' m//' => sub{ split( m/\r?\n/, $bar ); },
' m""' => sub{ split( m"\r?\n", $bar ); },
' qr//' => sub{ split( qr/\r?\n/, $bar ); },
' qq//' => sub{ split( qq/\r?\n/, $bar ); },
' ""' => sub{ split( "\r?\n", $bar ); },
'$qr ' => sub{ split( $qr, $bar ); },
'$str ' => sub{ split( $str, $bar ); },
'$qq ' => sub{ split( $qq, $bar ); }
);
cmpthese( -5, \%test, 'auto');
Benchmark: running "", //, m"", m//, qq//, qr//, $qq , $qr , $str for at least 5 CPU seconds... "": 6 wallclock secs ( 5.21 usr + 0.02 sys = 5.23 CPU) @ 42325.81/s (n=221364) //: 6 wallclock secs ( 5.26 usr + 0.00 sys = 5.26 CPU) @ 42626.24/s (n=224214) m"": 6 wallclock secs ( 5.30 usr + 0.01 sys = 5.31 CPU) @ 42519.96/s (n=225781) m//: 6 wallclock secs ( 5.20 usr + 0.00 sys = 5.20 CPU) @ 42568.08/s (n=221354) qq//: 6 wallclock secs ( 5.24 usr + 0.01 sys = 5.25 CPU) @ 42707.43/s (n=224214) qr//: 6 wallclock secs ( 5.11 usr + 0.03 sys = 5.14 CPU) @ 33277.04/s (n=171044) $qq : 5 wallclock secs ( 5.15 usr + 0.00 sys = 5.15 CPU) @ 42154.76/s (n=217097) $qr : 4 wallclock secs ( 5.28 usr + 0.00 sys = 5.28 CPU) @ 39593.94/s (n=209056) $str : 6 wallclock secs ( 5.29 usr + 0.00 sys = 5.29 CPU) @ 41843.86/s (n=221354) Rate qr// $qr $str $qq "" m"" m// // qq// qr// 33277/s -- -16% -20% -21% -21% -22% -22% -22% -22% $qr 39594/s 19% -- -5% -6% -6% -7% -7% -7% -7% $str 41844/s 26% 6% -- -1% -1% -2% -2% -2% -2% $qq 42155/s 27% 6% 1% -- -0% -1% -1% -1% -1% "" 42326/s 27% 7% 1% 0% -- -0% -1% -1% -1% m"" 42520/s 28% 7% 2% 1% 0% -- -0% -0% -0% m// 42568/s 28% 8% 2% 1% 1% 0% -- -0% -0% // 42626/s 28% 8% 2% 1% 1% 0% 0% -- -0% qq// 42707/s 28% 8% 2% 1% 1% 0% 0% 0% --
值得注意的是,这些速度基本相同,qr//
显示速度稍慢。在多次运行此测试后,qr//
和$qr
始终是最慢的,第二慢的。与其他人定期交换位置。
split()
设置正则表达式无关紧要。答案 4 :(得分:0)
split("\r?\n", $bar)
完全错误:split
内置函数需要将regexp指定为模式。只需使用perldoc -f split
阅读perl manual for split。
因此只能使用split(/\r?\n/, $bar)
。