【问题标题】:Perl replace multiple strings simultaneouslyPerl 同时替换多个字符串
【发布时间】:2013-05-25 11:30:19
【问题描述】:

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

$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"..

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

谢谢。

【问题讨论】:

  • 单词是否总是完整的单词或者是否有潜在的模式?

标签: regex arrays perl replace string-literals


【解决方案1】:

首先,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" 更正确。

【讨论】:

    【解决方案2】:

    嗯,主要是因为tr///d 与您的请求无关(tr/abc/12/d 将 a 替换为 1,b 替换为 2,并删除 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;
    

    【讨论】:

      猜你喜欢
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-31
      • 2019-04-19
      • 1970-01-01
      • 2010-10-06
      相关资源
      最近更新 更多