使用 sed 将多次出现的单词替换为列表中的单词

使用 sed 将多次出现的单词替换为列表中的单词

我有一个文件,其中包含多次出现的行的列表

output = filename
output = filename
output = filename
output = filename

我在 txt 文件中还有一个按时间顺序排列的文件名列表,我想用它来filename按以下顺序替换出现的内容

2d_slv_Nx.19800111.SUB.nc
2d_slv_Nx.19800213.SUB.nc
2d_slv_Nx.19800322.SUB.nc
2d_slv_Nx.19800510.SUB.nc

我想要以下输出

output = 2d_slv_Nx.19800111.SUB.nc
output = 2d_slv_Nx.19800213.SUB.nc
output = 2d_slv_Nx.19800322.SUB.nc
output = 2d_slv_Nx.19800510.SUB.nc

答案1

   $ cat tmplate.sh 
    output = filename

    output = filename

    output = filename

    output = filename

    $ cat mkrepl.sh 

   while read fname
   do
     sed -i -e "0,/filename/s/filename/$fname/" tmplate.sh
   done < tmplate.sh
   $ 

Bash 脚本:从 tmplate.sh 读取行,将每一行提取到变量中fname,然后sed使用 bash 替换运行。

使用sed

  • -i 内联编辑
  • -e 表达式:

使用范围从

  • 0 到 /filename/ 上的行,(从第 0 行开始使 sed 在第一次替换后停止)。
  • 替换filename$fname

答案2

这很容易用 来解决awk

sed与循环使用相比,此解决方案仅读取输入文件并写入输出文件一次,并且仅使用一个进程。对于较长的文件名列表,这会更快。


假设调用了包含文件名的文件filenames并且调用了包含要修改的行的输入input,您可以使用

awk 'NR == FNR {name[i++]=$0;next} /^output = filename$/ { $3 = name[j++]; } 1' filenames input > output

解释:

该条件NR == FNR仅适用于第一个文件。name[i++]=$0;将行保存在数组中namenext跳过对此行的进一步处理。 (也可以使用name[NR]=$0;next。)

/^output = filename$/匹配要替换的行,$3 = name[j++];用数组中的名称替换第三个字段。我使用了一个新的索引,j而不是i再次从 0 开始计数。

1是具有隐式默认操作的“始终为真”条件print

笔记:如果要修改的行在您的实际输入中看起来不同,则脚本可能无法工作。对于文件filenames包含的数据少于要替换的行数的情况,不会进行错误处理。

相关内容