从列表(或其他文件)中查找并替换匹配的多个参数

时间:2015-02-05 19:04:06

标签: regex shell sed

我编写了一个简单的shell脚本,但它的效率非常低。在较大的文件上运行需要很长时间。我正在寻找更快的解决方案。

示例输入文件:

data.csv

1,data,data
3,data,data
4,data,data
9,data,data
...

matches.txt

3
9
16
17
...

我编写的脚本遍历matches.txt中的每个项目。它使用sed来匹配csv文件中行的开头,并通过预先**对其进行注释。

#!/bin/bash

IFS=$'\r\n' GLOBIGNORE='*' :; XYZ=$(<matches.txt)
for id in ${XYZ[@]}
do
  sed -i '' "${id}s/^**//" data.csv
done

我使用OS X,因此sed参数略有不同。

1 个答案:

答案 0 :(得分:3)

不是在循环中调用sed,而是可以使用此awk:

awk -F ',' 'FNR==NR{a[$1]++; next} $1 in a{$0 = "**" $0} 1' matches.txt data.csv
1,data,data
**3,data,data
4,data,data
**9,data,data

保存awk的输出:

awk -F ',' 'FNR==NR{a[$1]++; next} $1 in a{$0 = "**" $0} 1' matches.txt data.csv > _tmp
mv _tmp data.csv

<强>解释

  • -F ',' - 使用字段分隔符作为逗号
  • FNR==NR - 为第一个文件执行此块
  • {a[$1]++; next} - 从第一个文件创建一个密钥为$1的数组,然后转到下一行
  • $1 in a{$0 = "**" $0} - 对于第二个文件,如果第一个字段位于数组a中,则在当前行中添加**
  • 1 - 默认awk动作(打印行)