尝试在第二个文件中匹配一个文件中的单词时,Grep 不起作用

尝试在第二个文件中匹配一个文件中的单词时,Grep 不起作用

我有 2 个文件,都有很多行,但只包含一个数字。我试图查看 file1 中的任何数字是否与 file2 中的数字匹配。这是我尝试过的,但由于某种原因它不起作用:

for i in $(cat file1); do grep ${i} file2; done

这里的前参考是来自 file1 和 file2 的数据

file1   file2
2134    1251
2135    5626
5342    4327
6456    8453
3413    4537
4525    3533
2347    5738
1235    1235
7453    3462

那么这个命令不应该获取文件 1 中的每一行并将其与整个文件 2 进行 grep 吗?在这种情况下,不应该在屏幕上打印匹配吗?

答案1

您只需要使用grep -f file1 file2或者您也可以使用cat file1 | grep -f /dev/stdin file2

答案2

给定两个普通的 Unix 文本文件,你的 shell 循环会打印

1235

因为这是两个文件中都出现的行。如果没有,那么您的文件之一可能是 DOS 文本文件。您可以使用该实用程序将 DOS 文本文件转换为 Unix 文本文件dos2unix

考虑到您拥有的数据类型,您的循环没有什么重大问题,除了它调用grep一次 for每一个行在file1.它还会匹配子字符串,例如100in 1001,并且如果任何行包含file1空格或制表符,它会将这些行拆分为多个单词(因为其中for i in $(cat ...)$(cat ...)加引号)。

如果您想解决您的问题方式(带循环),你最好这样做

while IFS= read -r word; do
    grep -xF -e "$word" file2
done <file1

和稍后在我的回答中进行解释,并表示下一个参数是要匹配的模式(否则,如果它以破折号()开头,则可以将其视为命令行-x选项。-F-e-

这仍然会grep为 中的每一行执行一次file1,但它会正确执行。


要提取与file2in 中的行完全对应的行file1,而不使用 shell 循环,您可以使用

$ grep -xF -f file1 file2
1235

这是假设file1包含一个合理的行数,但不要太多(“太多”将取决于您拥有的内存量)。

该命令使用grepwith -x,它强制仅跨整行进行匹配(无子字符串匹配),并且 with-F进行更改grep以进行字符串比较而不是正则表达式匹配。

指示从 读取模式(要匹配-f file1grep字符串)file1


对于真正大量的数据,使用效率会非常低grep。相反,对于此任务和这种类型的数据(单独行上的单个单词),最好在文件之间执行关系连接操作:

$ join file1 file2
1235

这个会,假设两个文件均按字典顺序排序,返回两个文件之间相同的数字。


使用comm

$ comm -1 -2 file1 file2
1235

comm还比较已排序文件并可以轻松处理非常大型数据集。它默认打印三列:

  1. 仅出现在第一个文件中的行
  2. 仅出现在第二个文件中的行
  3. 两个文件中都出现的行

我们-1关闭第一列的输出,并-2禁用第二列,只comm输出两个文件中相同的行。

相关内容