Bash 如何根据另一个文件中的列表值从csv文件中删除行?

Bash 如何根据另一个文件中的列表值从csv文件中删除行?,bash,csv,awk,sed,grep,Bash,Csv,Awk,Sed,Grep,我有两个文件: candidates.csv: id,value 1,123 4,1 2,5 50,5 1 2 5 3 10 黑名单.csv: id,value 1,123 4,1 2,5 50,5 1 2 5 3 10 我想删除candidates.csv中的所有行,其中第一列(id)的值包含在blacklist.csv中id始终是数字。在这种情况下,我希望我的输出如下所示: id,value 4,1 50,5 cat candidates.csv | cut -d \, -f 1

我有两个文件:

candidates.csv

id,value
1,123
4,1
2,5
50,5
1
2
5
3
10
黑名单.csv

id,value
1,123
4,1
2,5
50,5
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
到目前为止,我用于识别重复行的脚本如下所示:

id,value
4,1
50,5
cat candidates.csv | cut -d \, -f 1 | grep -f blacklist.csv -w
这给了我输出

1
2
$ sed -e 's/[0-9]+/&\,/g' blacklist.csv > filter.csv
$ grep -Fvf filter.csv candidates.csv
id,value
4,1
50,5

现在,我不知何故需要将这些信息重新导入
sed
/
awk
/
gawk
/。。。删除重复的,但我不知道怎么做。你知道我如何从这里继续下去吗?还是有更好的解决方案?我唯一的限制是它必须在bash中运行。

下面的情况如何:

 awk -F, '(NR==FNR){a[$1];next}!($1 in a)' blacklist.csv candidates.csv
join -v 1 -t, <(sort -t, candidates.csv) <(sort blacklist.csv)
这是如何工作的?

awk程序是一系列模式动作对,编写如下:

condition { action }
condition { action }
...
其中,
condition
通常是一个表达式,
action
是一系列命令。这里,第一个条件动作对为:

  • (NR==FNR){a[$1];next}
    如果总记录计数
    NR
    等于文件
    FNR
    的记录计数(即,如果我们正在读取第一个文件),则将所有值存储在数组
    a
    中,并跳到下一条记录(不要做任何其他事情)
  • !(a中的$1)
    如果第一个字段不在数组
    a
    中,则执行默认操作,即打印该行。这将只对第二个文件起作用,因为第一个条件操作对的条件不成立

您可以同时使用
sed
grep
来获得输出

1
2
$ 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
sed
中的
-r
相同


grep
使用选项
f
比较文件,然后使用
v
删除行
F
表示固定字符串

如果您不太关心
candidates.csv
文件中的行顺序,您可以使用以下选项:

 awk -F, '(NR==FNR){a[$1];next}!($1 in a)' blacklist.csv candidates.csv
join -v 1 -t, <(sort -t, candidates.csv) <(sort blacklist.csv)

join-v1-t,这里有一种保存头的方法:
{IFS=read-r头;echo“$header”;join-t,-v1