13

有什么办法可以替换一个字符串中的多个字符串?例如,我有字符串hello world what a lovely day,我想用其他东西替换what和..lovely

$sentence = "hello world what a lovely day";
@list = ("what", "lovely"); # strings to replace
@replist = ("its", "bad"); # strings to replace with
($val = $sentence) =~ "tr/@list/@replist/d";
print "$val\n"; # should print "hello world its a bad day"..

任何想法为什么它不起作用?

谢谢。

4

2 回答 2

13

首先,tr不是那样工作的;详情咨询perldoc perlop,但tr做音译,和代换有很大区别。

为此,更正确的替换方法是

# $val
$val =~ s/what/its/g;
$val =~ s/lovely/bad/g;

请注意,“同时”更改要困难得多,但我们可以做到,例如,

%replacements = ("what" => "its", "lovely" => "bad");
($val = $sentence) =~ s/(@{[join "|", keys %replacements]})/$replacements{$1}/g;

(当然,用元字符替换字符串可能需要转义。)

这仍然只是在术语的非常松散意义上是同时的,但对于大多数目的来说,它的作用就像替换是一次性完成的。

"what"此外,替换为"it's",而不是更正确"its"

于 2013-05-30T02:19:08.027 回答
6

好吧,主要是它不起作用,因为tr///d与您的请求无关(tr/abc/12/d用 1 替换 a,用 2 替换 b,并删除 c)。此外,默认情况下,数组不会以对您的任务有用的方式插入到正则表达式中。此外,如果没有哈希查找或子例程调用或其他逻辑之类的东西,您就无法在操作的右侧做出决定s///

要回答标题中的问题,您可以同时执行多个替换 - 呃,方便的连续 - 以这种方式:

#! /usr/bin/env perl
use common::sense;

my $sentence = "hello world what a lovely day";

for ($sentence) {
  s/what/it's/;
  s/lovely/bad/
}

say $sentence;

做一些更像你在这里尝试的事情:

#! /usr/bin/env perl
use common::sense;

my $sentence = "hello world what a lovely day";

my %replace = (
  what => "it's",
  lovely => 'bad'
);

$sentence =~ s/(@{[join '|', map { quotemeta($_) } keys %replace]})/$replace{$1}/g;

say $sentence;

如果您要进行大量此类替换,请先“编译”正则表达式:

my $matchkey = qr/@{[join '|', map { quotemeta($_) } keys %replace]}/;

...

$sentence =~ s/($matchkey)/$replace{$1}/g;

编辑:

并扩展我关于数组插值的评论,您可以更改$"

local $" = '|';
$sentence =~ s/(@{[keys %replace]})/$replace{$1}/g;
# --> $sentence =~ s/(what|lovely)/$replace{$1}/g;

确实,这并不能改善这里的情况,尽管如果您已经在数组中拥有了键,则可能会这样:

local $" = '|';
$sentence =~ s/(@keys)/$replace{$1}/g;
于 2013-05-30T02:23:28.733 回答