当找到匹配项时,将文件 a 中的子字符串替换为文件 b 中的字符串

当找到匹配项时,将文件 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 -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

无济于事。

答案1

您可以使用file1sed创建一个脚本,然后运行此脚本将 file2 转换为预期输出:sedsed

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在散列中。然后,它根据所有键(即来自的键)创建一个正则表达式,并遍历第二个文件并用存储在哈希中的值替换匹配项。如果有两个模式从同一位置开始,通常还会按长度对键进行排序以使用较长的字符串:

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

答案2

如果输出可以混合(不保留原始行顺序),则可以使用加入

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

答案3

如果您没有为两个文件选择不同的分隔符(:与=),那么这将是一个非常标准的查找任务,使用关联数组awk

如果您碰巧有 GNU 版本,awk您可以使用规则更改文件之间的分隔符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

相关内容