Замена подстроки в файле a строкой в ​​файле b при совпадении

У меня есть 2 файла.

Файл 1

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

Файл 2

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

Желаемый результат:

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

Я пробовал несколько вещей, самым последним из которых является загрузка двух файлов в массив и цикл с помощью sed.

 #!/bin/bash declare -aa readarray a <filea.txt echo $a declare -ab readarray b <fileb.txt echo $b for line in 'fileb.txt'; do sed -i -- 's/$line/$a/' file.txt done 

Но безрезультатно.

Вы можете использовать sed для создания сценария sed из файла1, а затем запустить sed с этим скриптом, чтобы превратить файл2 в ожидаемый результат:

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

Выход первого sed

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

Что явно выполняет нужные вам замены.

Вы также можете использовать perl, он будет работать даже для строк, содержащих косые черты и восклицательные знаки:

 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 

Он читает первый файл, разбивает каждую строку на = и сохраняет пару $from => $to в хеше. Затем он создает регулярное выражение из всех ключей (т. Е. Из s) и перебирает второй файл и заменяет совпадения значениями, хранящимися в хеше. Обычно также сортирует ключи по длине, чтобы использовать более длинную строку, если есть два шаблона, которые начинаются в одном и том же месте:

 map quotemeta, sort { length $b <=> length $a } keys %h; 

Если выход может быть смешанным (не сохраняя порядок оригинальных строк), вы можете использовать join

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

Если вы не выбрали разные разделители (: versus =) для двух файлов, это была бы довольно стандартная задача поиска с использованием ассоциативного массива в awk

Если у вас есть множество awk для GNU, вы можете менять разделители между файлами с помощью правила ENDFILE , что позволяет вам делать

 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