是否有与Perl兼容的正则表达式来修剪字符串两边的空格?
-
06-07-2019 - |
题
有没有办法在一行中做到这一点?
$x =~ s/^\s+//;
$x =~ s/\s+$//;
换句话说,从字符串中删除所有前导和尾随空格。
解决方案
$x =~ s/^\s+|\s+$//g;
或
s/^\s+//, s/\s+$// for $x;
其他提示
我的第一个问题是......为什么?我没有看到任何单正则表达式解决方案比你开始使用的正则表达式更具可读性。他们肯定不会那么快。
#!/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在另一个答案中建议使用更长的字符串(虽然一百万看起来像是矫枉过正)。然而,这也表明在你选择技巧风格之前,你要弄清楚你的字符串长度是什么样的 - 使用较短的字符串可以减少技巧的优点。尽管如此,我已经测试了双倍的胜利。它的眼睛仍然更容易。
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+$//;
(可以说)性能受到了打击,但只要你不关心执行时的几微秒,增加的可读性就值得。 IMHO。
在这里: $ x = ~s / \ A \ s *(。*?)\ s * \ z / $ 1 /;
代码>
$ x = ~s /(^ \ s +)|(\ s + $)// g;
我通常这样做:
($foo) = $foo =~ /^\s*(.*?)\s*$/;
前导空格和尾随空格之间的所有内容都被分组并返回,因此我可以将它分配给相同的旧变量。
或者这个: s / \ A \ s * | \ s * \ Z // g
s/^\s*(\S*\S)\s*$/$1/
$var1 =~ s/(^\s*)(.*?)(\s*$)+/$2/;
$x =~ s/^\s*(.*?)\s*$/$1/;