如何在保留原始字符串的同时对字符串执行Perl替换?


179

在Perl中,有什么好方法可以使用正则表达式对字符串进行替换并将值存储在不同的变量中,而无需更改原始值?

我通常只是将字符串复制到新变量,然后将其绑定到s///对新字符串进行替换的正则表达式,但是我想知道是否有更好的方法来做到这一点?

$newstring = $oldstring;
$newstring =~ s/foo/bar/g;

Answers:


256

这是我惯常使用的成语,无需更改原始字符串即可获得字符串的修改后的副本:

(my $newstring = $oldstring) =~ s/foo/bar/g;

在perl 5.14.0或更高版本中,可以使用新的/r 非破坏性替换修饰符

my $newstring = $oldstring =~ s/foo/bar/gr; 

注意:以上解决方案g无法正常工作。它们还可以与任何其他修饰符一起使用。


6
是否根据使用严格。最小范围变量++
ysth

我想知道是否my $new = $_ for $old =~ s/foo/bar;会起作用?
Benoit 2014年

2
@Benoit,我相信您的意思是s/foo/bar/ for my $newstring = $oldstring;它有效,但是很奇怪。
ikegami

43

该声明:

(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;

3
您是否忘记了g顶级正则表达式中的?
mareoraft


10

单行代码解决方案比起好的代码更有用。好的Perl编码人员会知道并理解它,但是它比您刚开始的两行复制和修改对联的透明度和可读性要差得多。

换句话说,执行此操作的一种好方法是您已经执行的操作。以可读性为代价的不必要的简洁并不是胜利。


嗯,但是在无意间修改错误字符串的问题中,单行版本不会出现错误。
2008年

单行版本<i>如果正确执行</ i>,则不是主题,而是真实的。但这是一个单独的问题。
乔什·米拉德

9
您可能会认为这是不必要的简洁,但是必须两次键入变量名才能使用一次,这是故障点数量的两倍。对于懂该语言的人来说,它是完全可读的,甚至在我们的<i> Learning Perl </ i>课程中也是如此。
brian d foy

1

另一个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

1

我讨厌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

2
这与原版有何不同?(我想您想要=~ s。)
Teepeemm 2016年

错误的错误。该代码的实际输出是newword donotnewword newword donotnewword newword donotnewword
Pascal

2
看看...如果JoGotta使用了传统的和熟悉的foobar,他的答案将是准确的。再次证明习俗的存在是有原因的,只能以艰难的方式来吸取教训。;)
Jon

-1

如果使用编写Perl use strict;,那么即使声明了该语法,也将发现单行语法无效。

带有:

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";

1
如果您选择use warnings;而不是-w,那么您将获得更大的控制权:例如,如果您要暂时关闭代码块中的警告。
glenn jackman 09年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.