在包含两个字线的文件中,grep只显示那些同时包含白名单中的单词的行

时间:2013-04-23 16:31:01

标签: awk grep whitelist

我有一个文件1:

green
yellow
apple
mango

和file2:

red apple
blue banana
yellow mango
purple cabbage

我需要从file2中找到两个单词属于file1中列表的元素。所以它应该显示:

  

黄芒果

我试过了:

awk < file2 '{if [grep -q $1 file1] && [grep -q $2 file1]; then print $0; fi}'

我收到语法错误。

3 个答案:

答案 0 :(得分:3)

这样可以解决问题:

$ awk 'NR==FNR{a[$0];next}($1 in a)&&($2 in a)' file1 file2 
yellow mango

<强>解释

NR是一个特殊的awk变量,用于跟踪输入中的当前行,FNR跟踪每个单独文件中的当前行,因此条件NR==FNR仅为真当我们在第一个文件中。 a是一个关联数组,其中键是第一个文件中的每个唯一行。 $0awk中当前行的值。 next语句跳转到文件中的下一行,不执行跳过的下一部分。如果第一个字段$1在数组a中,第二个字段然后打印当前行,则最后一部分是直接的。 awk中的默认块为{print $0},因此这是隐含的。

答案 1 :(得分:0)

你可以用bash,sed和grep:

来做
grep -f <(sed 's/^/^/' file1) file2  | grep -f <(sed 's/$/$/' file1)

这有点模糊,所以我会将其分解:

grep -f <file>从文件中读取一系列模式,并在任何模式上匹配。

<(...)bash process substitution并执行shell命令并创建一个伪文件,其输出可用于代替文件名。

sed 's/^/^/' file1在file1中每行的开头插入一个^字符,将这些行转换为与file2的第一个单词匹配的模式。

sed 's/$/$/' file1在末尾插入$字符,因此模式将匹配第二个字。

修改: 使用:

grep -f <(sed 's/^/^/;s/$/\b/' file1) file2  | grep -f <(sed 's/$/$/;s/^/\b/' file1)

解决Jonathan在评论中指出的问题。

答案 2 :(得分:0)

这是一种非常强硬的方法,可能不受许多grep / sed实现者的反对。此外,它可能是终端依赖的。你被警告了。

GNU grep,在彩色模式下,突出显示其中一个模式匹配的输入部分,理论上可以用作完全匹配的测试。在这里,这甚至可以在实践中起作用,也就是说,在GNU sed的帮助下:

grep --color=always -f file1 file2 | sed -n '/^\x1b.*\x1b\[K *\x1b.*\x1b\[K$/ { s/\x1b\[K//g; s/\x1b[^m]*m//gp }'

输出:

yellow mango

请注意,sed模式假定file2中的空格分隔列。