2

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.

#!/bin/bash    
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 
 done

To no avail.

1

3 Answers 3

4

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 (<>) {
              chomp;
              ($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;
5
  • 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? Commented Sep 20, 2016 at 15:26
  • Apologies. I was typing incorrectly. Can you help me understand why the double sed works? Commented Sep 20, 2016 at 15:30
  • @JeffCarson: What exactly is unclear? Do you understand the output of the first sed?
    – choroba
    Commented Sep 20, 2016 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! = Commented Sep 20, 2016 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
    Commented Sep 20, 2016 at 15:51
3

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)
1

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
2
  • Apologies, I could actually make the separators the same. Commented Sep 20, 2016 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 Commented Sep 20, 2016 at 15:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .