有没有办法在一行中做到这一点?
$x =~ s/^\s+//; $x =~ s/\s+$//;
换句话说,从字符串中删除所有前导和尾随空格.
我的第一个问题是......为什么?我没有看到任何单正则表达式解决方案比你开始使用的正则表达式更具可读性.他们肯定不会那么快.
#!/usr/bin/perl use strict; use warnings; use Benchmark qw(:all); my $a = 'a' x 1_000; my @x = ( " $a ", "$a ", $a, " $a" ); cmpthese(-5, { single => sub { for my $s (@x) { my $x = $s; $x =~ s/^\s+|\s+$//g; } }, double => sub { for my $s (@x) { my $x = $s; $x =~ s/^\s+//; $x =~ s/\s+$//; } }, trick => sub { for my $s (@x) { my $x = $s; s/^\s+//, s/\s+$// for $x; } }, capture => sub { for my $s (@x) { my $x = $s; $x =~ s/\A\s*(.*?)\s*\z/$1/ } }, kramercap => sub { for my $s (@x) { my $x = $s; ($x) = $x =~ /^\s*(.*?)\s*$/ } }, } );
给我的机器上的结果:
Rate single capture kramercap trick double single 2541/s -- -12% -13% -96% -96% capture 2902/s 14% -- -0% -95% -96% kramercap 2911/s 15% 0% -- -95% -96% trick 60381/s 2276% 1981% 1974% -- -7% double 65162/s 2464% 2145% 2138% 8% --
编辑:runrig是对的,但变化不大.我已经更新了代码以在修改之前复制字符串,这当然会减慢速度.我还考虑了brian d foy在另一个答案中建议使用更长的字符串(虽然一百万看起来像是矫枉过正).然而,这也表明在你选择技巧风格之前,你要弄清楚你的字符串长度是什么样的 - 使用较短的字符串可以减少技巧的优点.尽管如此,我已经测试了双倍的胜利.它在眼睛上仍然更容易.
$x =~ s/^\s+|\s+$//g;
要么
s/^\s+//, s/\s+$// for $x;
有趣的是你应该提起这件事!
我最近阅读了一篇文章,分析了十二种(!)不同修剪实现的性能.
虽然本文专门使用JavaScript正则表达式实现,但它使用Perl语法,所以我认为它适合这个讨论.
Tanktalus显示了非常小的字符串的基准,但随着字符串变大,问题变得更糟.在他的代码中,我更改了顶部:
my $a = 'a' x 1_000_000; my @x = ( " $a ", "$a ", $a, " $a" );
我得到这些结果:
Rate single capture trick double single 2.09/s -- -12% -98% -98% capture 2.37/s 13% -- -98% -98% trick 96.0/s 4491% 3948% -- -0% double 96.4/s 4512% 3967% 0% --
随着字符串越来越大,使用"技巧"和"双重"几乎是相同的,大多数人都会采用的常见解决方案,"单身"(包括我,因为即使我知道这一点,我也无法打破这种习惯),真的开始吮吸.
每当你看一个基准测试时,想一想它告诉你什么.要查看您是否理解,请更改数据并重试.使数组变长,标量变大,依此类推.使循环,greps或正则表达式在开始,中间和结束时找到东西.查看新结果是否与您的预测相符.弄清楚趋势是什么.性能是否越来越好,接近极限,峰值然后开始下降,还是其他什么?
从异端人士那里争论,为什么要这样呢?所有上述解决方案都是"正确的",因为它们在一次通过中从字符串的两侧修剪空白,但没有一个是非常可读的(期望可能是这一个).除非您的代码的受众由专家级Perl编码员组成,否则上述候选人中的每一位都应该有一个评论来描述他们的行为(无论如何都可能是一个好主意).相比之下,这两条线在不使用前瞻,通配符,中间体或任何对于经验适中的程序员来说不是很明显的事情的情况下完成相同的事情:
$string =~ s/^\s+//; $string =~ s/\s+$//;
(可以说)有一个性能损失,但只要您不关心执行时的几微秒,增加的可读性就值得.恕我直言.