Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can perl replace multiple keywords with their own substitute word in one go?

Tags:

regex

perl

Consider a textfile with the contents:

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

And consider the 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

This replaces every fruit with its colour.
Now, could this be done in a single s///g somehow, instead of the above four?

I am also concerned about the order of the fruit words.
If my sample does not include "apple", none of the other replacements will complete. How should I fix that?

Please note: I want to keep the solution as a one-liner.
So defining hashes, reading in files and other solutions requiring many lines of perl code do not take me forward.

It is more of a curiosity rather than a life-or-death question a project would depend on. Just troubles me for some days now and thought a more experienced perl user out there could help with the solution in a heartbeat, or put me out of my misery by telling me straight that this cannot be done in perl the way I want.

like image 674
Keve Avatar asked Jan 19 '12 21:01

Keve


1 Answers

Replace

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

with

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

Faster and doesn't have a problem with a=>b b=>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

Other potential issues:

  • What if you want to replace apple but not apples?
  • What if the hash has keys bee and beer?

Both problems can be solved using suitable anchoring (e.g. $re = qr/\b($re)\b/). The second can also be solved by sorting the keys by decreasing length (sort { length($b) <=> length($a) } keys %subs).

(You can remove the line breaks I added for readability.)

like image 144
ikegami Avatar answered Sep 29 '22 11:09

ikegami