我有两个文件:
candidates.csv
:
id,value
1,123
4,1
2,5
50,5
blacklist.csv
:
1
2
5
3
10
我想从candidates.csv
中删除第一行(id
)包含在blacklist.csv
中的值的所有行。 id
始终是数字。在这种情况下,我希望输出看起来像这样:
id,value
4,1
50,5
到目前为止,我用于识别重复行的脚本看起来像这样:
cat candidates.csv | cut -d \, -f 1 | grep -f blacklist.csv -w
这给了我输出
1
2
现在,我不知何故需要将此信息通过管道传送回sed
/ awk
/ gawk
/ ...中,以删除重复项,但我不知道如何做。有什么想法我可以从这里继续吗?还是有更好的解决方案?我唯一的限制是它必须在bash中运行。
答案 0 :(得分:6)
以下内容如何:
awk -F, '(NR==FNR){a[$1];next}!($1 in a)' blacklist.csv candidates.csv
这是如何工作的?
awk程序是一系列模式-动作对,写为:
condition { action }
condition { action }
...
其中condition
通常是一个表达式,action
是一系列命令。在这里,第一个条件操作对为:
(NR==FNR){a[$1];next}
,如果总记录数NR
等于文件FNR
的记录数(即,如果我们正在读取第一个文件),则将所有值存储在数组{{1}中}并跳至下一条记录(不执行其他任何操作)a
如果第一个字段不在数组!($1 in a)
中,则执行默认操作,即打印行。由于第一个条件操作对的条件不成立,因此只能在第二个文件上使用。答案 1 :(得分:1)
如果您不太担心candidates.csv
文件中各行的顺序,可以使用以下命令:
join -v 1 -t, <(sort -t, candidates.csv) <(sort blacklist.csv)
-v 1
从第一个文件(排序后的candidates.csv
)请求所有与第一字段和第二个文件(blacklist.csv
)不匹配的行。 -t,
只是将逗号设置为分隔符。
如果您担心candidates.csv
文件中的标题行,可以在排序或更改顺序之前将其删除。
答案 2 :(得分:0)
您可以同时使用sed
和grep
来获取输出
$ sed -e 's/[0-9]+/&\,/g' blacklist.csv > filter.csv
$ grep -Fvf filter.csv candidates.csv
id,value
4,1
50,5
sed
命令向每个,
添加id
并输出到filter.csv
。 E
用于解释MacOSX / FreeBSD中的正则表达式,与GNU -r
中的sed
相同。
grep
使用选项f
在文件之间进行比较,然后使用v
删除行。 F
用于固定字符串。