【发布时间】:2010-09-06 13:47:51
【问题描述】:
在 Perl 中,使用正则表达式对字符串执行替换并将值存储在不同变量中而不更改原始值的好方法是什么?
我通常只是将字符串复制到一个新变量,然后将其绑定到对新字符串进行替换的s/// 正则表达式,但我想知道是否有更好的方法来做到这一点?
$newstring = $oldstring;
$newstring =~ s/foo/bar/g;
【问题讨论】:
在 Perl 中,使用正则表达式对字符串执行替换并将值存储在不同变量中而不更改原始值的好方法是什么?
我通常只是将字符串复制到一个新变量,然后将其绑定到对新字符串进行替换的s/// 正则表达式,但我想知道是否有更好的方法来做到这一点?
$newstring = $oldstring;
$newstring =~ s/foo/bar/g;
【问题讨论】:
这是我一直用来在不更改原始字符串的情况下获取字符串的修改副本的习语:
(my $newstring = $oldstring) =~ s/foo/bar/g;
在 perl 5.14.0 或更高版本中,您可以使用新的/r non-destructive substitution modifier:
my $newstring = $oldstring =~ s/foo/bar/gr;
注意:
上述解决方案也可以在没有g 的情况下使用。它们也适用于任何其他修饰符。
另请参阅:perldoc perlrequick: Perl regular expressions quick start
【讨论】:
my $new = $_ for $old =~ s/foo/bar; 这样的东西是否可行?
s/foo/bar/ for my $newstring = $oldstring; 它有效,但它更奇怪。
声明:
(my $newstring = $oldstring) =~ s/foo/bar/g;
相当于:
my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;
或者,从 Perl 5.13.2 开始,您可以使用 /r 进行非破坏性替换:
use 5.013;
#...
my $newstring = $oldstring =~ s/foo/bar/gr;
【讨论】:
g?
在use strict 下,说:
(my $new = $original) =~ s/foo/bar/;
改为。
【讨论】:
单行解决方案作为陈词滥调比好的代码更有用;优秀的 Perl 编码人员会知道并理解它,但它的透明度和可读性远不如您开始使用的两行复制和修改对联。
换句话说,一个很好的方法就是你已经这样做了。以可读性为代价的不必要的简洁不是胜利。
【讨论】:
另一个 5.14 之前的解决方案:http://www.perlmonks.org/?node_id=346719(参见 japhy 的帖子)
由于他的方法使用map,它也适用于数组,但需要级联map 来生成临时数组(否则会修改原始数组):
my @orig = ('this', 'this sucks', 'what is this?');
my @list = map { s/this/that/; $_ } map { $_ } @orig;
# @orig unmodified
【讨论】:
如果你用use strict; 编写 Perl,那么你会发现单行语法是无效的,即使在声明时也是如此。
与:
my ($newstring = $oldstring) =~ s/foo/bar/;
你得到:
Can't declare scalar assignment in "my" at script.pl line 7, near ") =~"
Execution of script.pl aborted due to compilation errors.
相反,您一直使用的语法虽然更长,但在语法上是使用use strict; 的正确方法。对我来说,现在使用use strict; 只是一种习惯。我自动做。每个人都应该这样做。
#!/usr/bin/env perl -wT
use strict;
my $oldstring = "foo one foo two foo three";
my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;
print "$oldstring","\n";
print "$newstring","\n";
【讨论】:
use warnings; 而不是-w,您可以获得更大的控制权:例如,如果您想暂时关闭代码块中的警告。
我讨厌 foo 和 bar .. 到底是谁在编程中想出了这些非描述性的术语?
my $oldstring = "replace donotreplace replace donotreplace replace donotreplace";
my $newstring = $oldstring;
$newstring =~ s/replace/newword/g; # inplace replacement
print $newstring;
%: newword donotreplace newword donotreplace newword donotreplace
【讨论】:
=~ s。)
newword donotnewword newword donotnewword newword donotnewword
foo 和 bar,他的答案将是准确的。再一次证明,习俗的存在是有原因的,而教训只能通过艰难的方式吸取。 ;)
如果我只是在 oneliner 中使用它,怎么样,sprintf("%s", $oldstring)
【讨论】: