Perl可以一次性用自己的替代词替换多个关键词吗?

时间:2012-01-19 21:53:11

标签: regex perl

考虑一个包含以下内容的文本文件:

apple apple pear plum apple cherry pear apple  
cherry plum plum pear apple cherry pear pear apple plum

并考虑perl one-liner:

perl -pe "s/apple/green/g and s/pear/yellow/g and s/plum/blue/g and s/cherry/red/g" < fruits.txt

这取代了每种水果的颜色 现在,这可以用一个s /// g以某种方式完成,而不是上面的四个吗?

我也关注水果词的顺序 如果我的样本不包含“apple”,则其他替换都不会完成。 我该如何解决这个问题?

请注意:我希望将解决方案保持为单行。
因此,定义哈希,读取文件以及需要多行perl代码的其他解决方案并不会让我前进。

这更像是一个好奇心,而不是一个项目所依赖的生死攸关的问题。 现在困扰我好几天了,并且认为一个更有经验的perl用户可以帮助解决心跳,或者让我摆脱困境,直接告诉我这不可能以我想要的方式完成。

5 个答案:

答案 0 :(得分:12)

替换

perl -pe's/apple/green/g and s/pear/yellow/g and ...' fruits.txt

perl -pe's/apple/green/g; s/pear/yellow/g; ...' fruits.txt

更快且a =&gt; b b =&gt; c:

没有问题
perl -pe'
   BEGIN {
      %subs=qw(apple green pear yellow plum blue cherry red);
      $re=join "|", map quotemeta, keys %subs;
      $re = qr/($re)/;
   }
   s/$re/$subs{$1}/g;
' fruits.txt

其他潜在问题:

  • 如果您要替换apple而不是apples
  • ,该怎么办?
  • 如果哈希有密钥beebeer怎么办?

使用适当的锚定(例如$re = qr/\b($re)\b/)可以解决这两个问题。第二个也可以通过减少长度(sort { length($b) <=> length($a) } keys %subs)对键进行排序来解决。

(您可以删除我为了便于阅读而添加的换行符。)

答案 1 :(得分:5)

perl -pe '%a=qw(apple green pear yellow plum blue cherry red);$b=join("|",keys %a);s/($b)/$a{$1}/g' < fruits.txt

答案 2 :(得分:4)

perl -E 'my %h = qw(apple green foo bar); say "apple foo" =~ s/(apple|foo)/$h{$1}/rge;'

答案 3 :(得分:1)

根据问题,我认为我只是有点草率,看看每一次非空白的运行。如果它有趣,我会替换它。如果没有,我会回复相同的文字。

 $ perl5.14.2 -nE 'print s/(\S+)/$h{$1}?$h{$1}:$1/rge}BEGIN{%h=qw(apple green pear yellow plum blue cherry red)'

如果问题比这更复杂,我的单行会看起来像:

 $ perl fruits2color

其他几个答案通过加入字符串来加强正则表达式。在非单行程序中,我可能会使用Regex::AssembleRegexp::Trie这样的程序。这些模块可以建立有效的交替。

答案 4 :(得分:0)

谁说哈希不记得他们的订单:)?

  

How can I make my hash remember the order I put elements into it?

     

使用Tie::IxHash   CPAN。

use Tie::IxHash;
tie my %myhash, 'Tie::IxHash';

for (my $i=0; $i<20; $i++) {
    $myhash{$i} = 2*$i;
}

my @keys = keys %myhash;
# @keys = (0,1,2,3,...)

$ perl -MTie::IxHash -pe '
         BEGIN { tie %h, "Tie::IxHash";
                 %h = qw< apple green pear yellow >;
               }
         s<($_)>/$h{$1}/g for keys %h;
        ' file