I have 2 files.

File 1

This is a string = mystringrocks
This is another string = mystringrocksmore

File 2

Trying to figure out: This is a string
Still trying to figure it out: This is another string

Desired output:

Trying to figure out: mystringrocks
Still trying to figure it out: mystringrocksmore

I've tried a number of things, the most recent of which is to load the two files into an array and looping with sed.

declare -a a
readarray a <filea.txt
echo $a

declare -a b
readarray b <fileb.txt
echo $b

for line in 'fileb.txt';
 do sed -i -- 's/$line/$a/' file.txt 

To no avail.


You can use sed to create a sed script from file1, and then run sed with this script to turn file2 into the expected output:

sed 's!^!s/!;s! = !/!;s!$!/!' file1 | sed -f- file2

The first sed's output is

s/This is a string/mystringrocks/
s/This is another string/mystringrocksmore/

Which clearly executes the substitutions you need.

You can also use perl, it will work even for strings containing slashes and exclamation marks:

perl -wE 'while (<>) {
              ($from, $to) = split / = /;
              $h{$from} = $to;
              last if eof;
          $regex = join "|", map quotemeta, keys %h;
          s/($regex)/$h{$1}/, print while <>
         ' file1 file2

It reads the first file, splits each line on = and stores the pair $from => $to in a hash. Then, it creates a regex from all the keys (i.e. from's), and goes over the second file and replaces the matches by the values stored in the hash. One also usually sorts the keys by length to use the longer string if there are two patterns that start at the same place:

map quotemeta, sort { length $b <=> length $a } keys %h;
  • I get sed: file - line 1: unterminated `s' command running the 2 sed method. This looks intriguing. If I remove the second sed after pipe I don't get that error. Am I doing something wrong? – Jeff Carson Sep 20 '16 at 15:26
  • Apologies. I was typing incorrectly. Can you help me understand why the double sed works? – Jeff Carson Sep 20 '16 at 15:30
  • @JeffCarson: What exactly is unclear? Do you understand the output of the first sed? – choroba Sep 20 '16 at 15:37
  • I am clear on what the output of the first sed is, I am wondering if you could help me understand the notation of how it is obtained. Specifcally, the 's!^!s/!;s! = – Jeff Carson Sep 20 '16 at 15:48
  • @JeffCarson: Ah, ok. I used ! instead of /, because I needed / in the generated output and I didn't want to bother myself with backslashes. So, it just says "put s/ at the beginning, replace _=_ with /, and put / at the end. – choroba Sep 20 '16 at 15:51

If the output can be mixed (do not keep original lines order) you can use join

join -o 2.1,1.2 -2 2 -t':' \
    <(sed 's/^/ /;s/ =/:/' File1 |sort -t: -k1,1)\
    <(sort -t: -k2 File2)

If you hadn't chosen different separators (: versus =) for the two files, it would have been a pretty standard lookup task using an associative array in awk

If you happen to have the GNU variety of awk you could change separators between files using an ENDFILE rule, allowing you to do

gawk 'BEGIN{FS=" = "} NR==FNR {a[$1]=$2;next} ENDFILE{FS=": "; OFS=FS;} {print $1, a[$2]}' file1 file2
Trying to figure out: mystringrocks
Still trying to figure it out: mystringrocksmore
  • Apologies, I could actually make the separators the same. – Jeff Carson Sep 20 '16 at 15:27
  • @JeffCarson n that case you can remove the ENDFILE rule and set a single global field separator using the -F command line switch – steeldriver Sep 20 '16 at 15:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.