Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace multiple patterns, but not with the same string

Tags:

bash

sed

is it possible to change multiply patterns to different values at the same command? lets say I have

A B C D ABC

and I want to change every A to 1 every B to 2 and every C to 3

so the output will be

1 2 3 D 123

since I have 3 patterns to change I would like to avoid substitute them separately. I thought there would be something like

sed -r s/'(A|B|C)'/(1|2|3)/ 

but of course this just replace A or B or C to (1|2|3). I should just mention that my real patterns are more complicated than that...

thank you!

like image 481
ornit Avatar asked Apr 13 '15 13:04

ornit


People also ask

How do I replace multiples in a string?

replace(/cat/gi, "dog"); // now str = "I have a dog, a dog, and a goat." str = str. replace(/dog/gi, "goat"); // now str = "I have a goat, a goat, and a goat." str = str. replace(/goat/gi, "cat"); // now str = "I have a cat, a cat, and a cat."

How do you replace some text pattern with another text pattern in a file?

`sed` command is one of the ways to do replacement task. This command can be used to replace text in a string or a file by using a different pattern.

How do you replace multiple values?

Find and replace multiple values with nested SUBSTITUTE The easiest way to find and replace multiple entries in Excel is by using the SUBSTITUTE function. The formula's logic is very simple: you write a few individual functions to replace an old value with a new one.

How do you replace multiple values in a string in python?

Method 3: Replace multiple characters using re.subn() is similar to sub() in all ways, except in its way of providing output. It returns a tuple with a count of the total of replacement and the new string rather than just the string.


2 Answers

Easy in Perl:

perl -pe '%h = (A => 1, B => 2, C => 3); s/(A|B|C)/$h{$1}/g'

If you use more complex patterns, put the more specific ones before the more general ones in the alternative list. Sorting by length might be enough:

perl -pe 'BEGIN { %h = (A => 1, AA => 2, AAA => 3);
              $re = join "|", sort { length $b <=> length $a } keys %h; }
          s/($re)/$h{$1}/g'

To add word or line boundaries, just change the pattern to

/\b($re)\b/
# or
/^($re)$/
# resp.
like image 188
choroba Avatar answered Sep 23 '22 18:09

choroba


Easy in sed:

sed 's/WORD1/NEW_WORD1/g;s/WORD2/NEW_WORD2/g;s/WORD3/NEW_WORD3/g'

You can separate multiple commands on the same line by a ;


Update

Probably this was too easy. NeronLeVelu pointed out that the above command can lead to unwanted results because the second substitution might even touch results of the first substitution (and so on).

If you care about this you can avoid this side effect with the t command. The t command branches to the end of the script, but only if a substitution did happen:

sed 's/WORD1/NEW_WORD1/g;t;s/WORD2/NEW_WORD2/g;t;s/WORD3/NEW_WORD3/g'  
like image 39
hek2mgl Avatar answered Sep 24 '22 18:09

hek2mgl