关于正则表达式:如何在保留原始字符串的同时对字符串执行Perl替换?

关于正则表达式:如何在保留原始字符串的同时对字符串执行Perl替换?

How do I perform a Perl substitution on a string while keeping the original?

在Perl中,使用正则表达式对字符串执行替换并将值存储在另一个变量中而不更改原始值的好方法是什么?

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

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

这是我用来获取字符串的修改副本而不更改原始字体的习语:

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

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

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

注意:上述解决方案也可以在没有g的情况下工作。它们也适用于任何其他修饰符。


该声明:

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

这相当于:

1
2
my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;

或者,从Perl 5.13.2开始,您可以使用/r进行非破坏性替换:

1
2
3
use 5.013;
#...
my $newstring = $oldstring =~ s/foo/bar/gr;


use strict下,说:

1
(my $new = $original) =~ s/foo/bar/;

代替。


单线解决方案作为一个shibboleth比良好的代码更有用;好的Perl程序员会知道它并理解它,但它比你刚开始的两行复制和修改联接更不透明和可读。

换句话说,这样做的好方法就是你已经这样做了。以可读性为代价的不必要的简洁并不是一个胜利。


另一个5.14之前的解决方案:http://www.perlmonks.org/?node_id = 346719(参见japhy的帖子)

由于他的方法使用map,它也适用于数组,但需要级联map来生成一个临时数组(否则原来会被修改):

1
2
3
my @orig = ('this', 'this sucks', 'what is this?');
my @list = map { s/this/that/; $_ } map { $_ } @orig;
# @orig unmodified

我讨厌foo和bar ..无论如何,他们在编程中想到了这些非描述性的术语?

1
2
3
4
5
6
7
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


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

附:

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

你得到:

1
2
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;现在只是一种习惯。我是自动完成的。大家应该。

1
2
3
4
5
6
7
8
9
10
11
12
#!/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","
"
;
print"$newstring","
"
;

推荐阅读