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

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

$newstring = $oldstring;
$newstring =~ s/foo/bar/g;
有帮助吗?

解决方案

这是我一直用来获取字符串的修改副本而不更改原始字符串的惯用法:

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

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

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

笔记:上述解决方案无需 g 也。它们还可以与任何其他修饰符一起使用。

其他提示

该声明:

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

在下面 use strict, , 说:

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

反而。

一行解决方案作为一种陈词滥调比好的代码更有用;优秀的 Perl 程序员会知道并理解它,但它比您开始使用的两行复制和修改对句更不透明和可读。

换句话说,做到这一点的一个好方法就是你的方式 已经 正在做。以牺牲可读性为代价的不必要的简洁并不是胜利。

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

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

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

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

如果你用以下方式编写 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";
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top