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

Posted

技术标签:

【中文标题】如何在保留原始字符串的同时对字符串执行 Perl 替换?【英文标题】:How do I perform a Perl substitution on a string while keeping the original? 【发布时间】:2010-09-06 13:47:51 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

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

(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; 这样的东西是否可行? @Benoit,我相信你的意思是s/foo/bar/ for my $newstring = $oldstring; 它有效,但它更奇怪。【参考方案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;

【讨论】:

您是否忘记了***正则表达式中的g【参考方案3】:

use strict 下,说:

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

改为。

【讨论】:

【参考方案4】:

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

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

【讨论】:

嗯,但是单行版本不会出现无意修改错误字符串的问题。 单行版本,如果正确执行,不是主题,是真的。但这是一个单独的问题。 您可能会认为这是不必要的简洁,但必须键入两次变量名才能使用一次它是失败点数的两倍。它对于了解该语言的人来说是完全可读的,甚至在我们的 Learning Perl 课程中。【参考方案5】:

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

【讨论】:

【参考方案6】:

如果你用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,您可以获得更大的控制权:例如,如果您想暂时关闭代码块中的警告。【参考方案7】:

我讨厌 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。) Clbuttic 错误。该代码的实际输出是newword donotnewword newword donotnewword newword donotnewword 看...如果 JoGotta 使用的是传统且熟悉的 foobar,他的答案将是准确的。再一次证明,习俗的存在是有原因的,而教训只能通过艰难的方式吸取。 ;) Clbuttic reference 谁?***有part of the answer。包括:“foobar 的词源可能来源于二战时期的军事俚语 FUBAR,它被贬义为 foobar。更早使用了 foo 这个词本身。...... 1965 年版的 MIT 技术工程新闻中出现了编程上下文中的印刷术语。”【参考方案8】:

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

【讨论】:

以上是关于如何在保留原始字符串的同时对字符串执行 Perl 替换?的主要内容,如果未能解决你的问题,请参考以下文章

如何在保留顺序的同时删除列表中的重复元素?

Pandas - 在保留原始列的同时创建具有替换值的新列

是否可以在 Perl 中保留哈希表的大小?

如何在保留格式的同时对用户生成的 HTML 块进行子串化?

如何在 JavaScript 中反转数组,同时保留原始数组的原始值? [复制]

Perl实例---批量替换内容