仅显示匹配的字符串 - grep

3

I have two files. File1 is as follows

Apple
Cat
Bat

以下是File2的内容

I have an Apple
Batman returns
This is a test file. 

现在我想检查第一个文件中哪些字符串不在第二个文件中。我可以执行grep -f file1 file2,但这只会给出第二个文件中匹配的行。

2
标题有点令人困惑。请尝试更清楚地表明您想显示不在file2中的行。 - fedorqui
2个回答

5
获取同时存在于第一个文件和第二个文件中的字符串:
grep -of file1 file2

使用给定的示例,结果将如下所示:
Apple
Bat

为了获取在第一个文件中但不在第二个文件中的字符串,您可以执行以下操作:
grep -of file1 file2 | cat - file1 | sort | uniq -u

甚至更简单(感谢@triplee的评论):
grep -of file1 file2 | grep -vxFf - file1

结果(使用给定示例)将是:
Cat

来自grep命令的手册页:

-o, --only-matching
只打印匹配行中已匹配(非空)的部分,在单独的输出行中打印每个该样的部分。

来自uniq命令的手册页:

-u, --unique
仅打印唯一的行。


2
后者可以简化为 grep -of file1 file2 | grep -vxFf - file1 - tripleee
虽然我认为这种方法很好,但打开文件两次进行检查有点过度。我承认在我的第一个解决方案中也这样做了,但如果性能很重要,我们的尝试将会非常“昂贵” :) - fedorqui

0
如果你想展示在file1中出现但是在file2中没有的单词,一种简单粗暴的方法是循环遍历这些单词并使用grep进行匹配。如果没有匹配成功,则打印该单词。
while read word
do
    grep -q "$word" f2 || echo "$word"
done < f1

为了匹配精确的单词,请添加-wgrep -wq...

测试

$ while read word; do grep -q "$word" f2 || echo "$word"; done < f1
Cat
$ while read word; do grep -wq "$word" f2 || echo "$word"; done < f1
Cat
Bat

更好的方法是使用awk:
$ awk 'FNR==NR {a[$1]; next} {for (i=1;i<=NF;i++) {if ($i in a) delete a[$i]}} END {for (i in a) print i}' f1 f2
Cat 
Bat 

这将文件file1中的值存储到数组a[]中。然后,它循环遍历file2的所有行,检查每个单独的元素。如果其中一个与数组a[]中的值匹配,则将该元素从数组中删除。最后,在END{}块中打印未找到的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接