How to replace a list of strings by another list

5

I have a file which has (many) strings I'd like to replace, so I thought about using a simple command like:

sed 's/string1/string2/g' file1 > out  

However, there are too many strings for that to be repeated manually. So I made a list of all the strings to be replaced, each in a line, and named it file A. Then I made a list of all the replacement strings, and named it file B.

Is there a way to do something like:

sed 's/line i of file A/line i of file B/g' file1 > out

for each line of file A?

Asasuser

Posted 2013-01-11T23:01:38.003

Reputation: 51

Answers

3

It would be easier to create a file with both the input and replacement strings on the same line (assuming that neither input nor replacement strings contain spaces). Then you can do so something simple like:

while read n k; do sed -i "s/$n/$k/g" file1; done < fileA

EDIT:

After seeing Nykakin's answer, I realized you can do the same thing with the two files you have combining his suggestion with mine:

paste fileA fileB | while read n k; do sed -i "s/$n/$k/g" file1; done 

terdon

Posted 2013-01-11T23:01:38.003

Reputation: 45 216

1NIce, this worked! just in my case I needed to use double quotes ("s/$n/$k/g" instead of 's/$n/$k/g')
Also, if it helps anybody I'd name the files like this:
fileA --> replace_what
fileB --> replace_with
file1 --> file_to_process
^^
– aesede – 2015-07-01T21:19:40.520

+1, this answer is simpler than mine and doesn't require subshell. – Nykakin – 2013-01-12T01:38:50.487

1

This is basically your first idea, but with the substitution commands put into a file, so they’re more manageable:

tmpfile=/tmp/Asasuser.$$
exec 3< fileA
exec 4< fileB
while read –r astring <&3
do
        read –r bstring <&4
        echo "s/$astring/$bstring/" >> "$tmpfile"
done
exec 3<&- 4<&-
sed –f "$tmpfile" file1 > out
rm –f "$tmpfile"

This assumes that fileA and fileB have the same number of lines (and that that number is greater than zero) and that neither of them has any unescaped / characters.

Scott

Posted 2013-01-11T23:01:38.003

Reputation: 17 653

1

We can just generate command that we need. Let's say that files with lists are called lista and listb. Then we can use:

$ for i in $(paste lista listb -d/); do echo -n "-e 's/$i/g' "; done

to generate option for sed. Now we can use it with eval. Let's say our file is called test. We use:

$ eval "sed" $(for i in $(paste lista listb -d/); do echo -n "-e 's/$i/g' "; done) "test"

Nykakin

Posted 2013-01-11T23:01:38.003

Reputation: 291

You don't need the eval (see my answer) but +1 for paste, I hadn't thought of that. – terdon – 2013-01-12T01:35:22.083

0

paste -d : fileA fileB | sed 's/\([^:]*\):\([^:]*\)/s%\1%\2%/' > sed.script
sed -f  sed.script SOURCE-FILE

SOURCE-FILE may be either an individual file or multiple files. The text in fileA and fileB cannot contain either colon or percent characters, but may contain blank characters.

karel

Posted 2013-01-11T23:01:38.003

Reputation: 11 374