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

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

提问人:kaybenleroll 提问时间:8/23/2008 最后编辑:the Tin Mankaybenleroll 更新时间:5/13/2021 访问量:242772

问:

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

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

$newstring = $oldstring;
$newstring =~ s/foo/bar/g;
正则表达式 Perl 替换

评论


答:

300赞 John Siracusa 8/23/2008 #1

这是我一直用来在不更改原始内容的情况下获取字符串的修改副本的习语:

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

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

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

注意:
上述解决方案也不起作用。它们也适用于任何其他修饰符。
g

也可以看看perldoc perlrequick:Perl 正则表达式快速入门

评论

6赞 ysth 9/19/2008
是否严格使用。变量的最小范围++,
0赞 Benny 5/1/2014
我想知道类似的东西是否可行?my $new = $_ for $old =~ s/foo/bar;
2赞 ikegami 2/23/2017
@Benoit,我相信你的意思是它有效,但它更奇怪。s/foo/bar/ for my $newstring = $oldstring;
51赞 Pat 8/23/2008 #2

声明:

(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赞 mareoraft 9/11/2014
你忘了你的顶级正则表达式吗?g
1赞 Tim Kennedy 9/11/2008 #3

如果你用 编写 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";

评论

3赞 glenn jackman 10/21/2009
如果代替 ,则可以获得更大的控制权:例如,如果要暂时关闭代码块中的警告。use warnings;-w
26赞 Sam Kington 9/15/2008 #4

在 下,说:use strict

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

相反。

14赞 Josh Millard 9/19/2008 #5

单行解决方案作为 shibboleth 比好的代码更有用;优秀的 Perl 程序员会知道并理解它,但它的透明度和可读性远不如你开始的两行复制和修改对联。

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

评论

0赞 ysth 9/19/2008
啊,但是一行版本不会出现无意中修改错误字符串的问题。
1赞 Josh Millard 9/19/2008
一行版本 <i>如果正确执行</i>,则不是主题,true。但这是一个单独的问题。
13赞 brian d foy 9/21/2008
您可能认为这是不必要的简洁,但必须键入两次变量名称才能使用它一次,这是故障点数的两倍。对于懂这门语言的人来说,它完全可以阅读,甚至在我们的 <i>Learning Perl</i> 课程中也是如此。
1赞 JoGotta 3/7/2016 #6

我讨厌 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赞 Teepeemm 4/23/2016
这与原版有何不同?(我想你想要。=~ s
2赞 Pascal 9/20/2017
Clbuttic错误。该代码的实际输出为newword donotnewword newword donotnewword newword donotnewword
3赞 Jon 9/21/2018
看。。。如果JoGotta使用传统的和熟悉的和,他的答案将是准确的。再一次证明,习俗的存在是有原因的,只有通过艰难的方式才能吸取教训。;)foobar
0赞 Peter Mortensen 4/29/2021
Clbuttic 参考文献
0赞 Peter Mortensen 4/29/2021
谁?维基百科有部分答案。包括:“foobar 的词源可能来源于二战时期的军事俚语 FUBAR,它被鞠躬为 foobar。foo 这个词本身在前面就被使用过。...这些术语在编程环境中的首次使用出现在 1965 年版的麻省理工学院技术工程新闻中。
2赞 textral 5/25/2017 #7

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

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

my @orig = ('this', 'this sucks', 'what is this?');
my @list = map { s/this/that/; $_ } map { $_ } @orig;
# @orig unmodified
1赞 ngn999 5/13/2021 #8

如果我只是在 oneliner 中使用它,怎么样,sprintf("%s", $oldstring)