【问题标题】:how to grep exact string match across 2 files如何在 2 个文件中 grep 精确字符串匹配
【发布时间】:2015-04-13 11:29:06
【问题描述】:

我在list1.txtlist2.txt 中有用户名的UTF-8 纯文本列表,每行1 个。请注意,如果相关,用户名可能包含正则表达式字符,例如! ^ . ( 等以及空格。

我想获取并保存到matches.txt 一个列表,其中包含两个 列表中出现的所有唯一值。我几乎没有命令行专业知识,但这几乎可以让我到达那里:

grep -Ff list1.txt list2.txt > matches.txt

...但这将"jdoe""jdoe III" 视为匹配,返回"jdoe III" 作为匹配值。这对于任务是不正确的。我需要每行模式匹配是 整个 行,即从 ^ 到 $。我尝试添加 -x 标志,但根本没有匹配项(编辑:请参阅已接受答案的评论 - 我的标志顺序错误)。

我在 OS X 10.9.5 上,我不必使用 grep - 另一个解决问题的命令行(工具)就可以了。

【问题讨论】:

  • 如果文件已排序,那么comm -1 -2 list1.txt list2.txt 可能会做你想做的事。
  • 我希望能找到一个更好的副本,建议grep -Fxf。这是一个常见问题解答,所以我确定有一个,但我找不到它。
  • 好吧,我确实花了一些时间寻找 SO 答案,因为我认为这是常见问题解答,但很多事情都很接近,但回答了不同的问题(不同到无法帮助没有 shell/CL 工具经验的人)。我找到的最有用的答案是 How to grep the exact match,尽管对于上述用例来说它失败了。
  • 指向建议的备用线程的链接不回答这个问题(也许有人可以删除该横幅 - 它并不能真正帮助寻找答案的人这个问题)。同样,triplee 给出的链接也没有回答这个问题。

标签: regex shell grep osx-mavericks


【解决方案1】:

这里的awkgrep 更方便:

awk 'FNR==NR{a[$0]; next} $0 in a' list1.txt list2.txt > matches.txt

$0 是行,FNR 是当前文件的当前行号,NR 是总行号(它们仅在您在第一个文件上时相同)。 a[$0] 是一个关联数组(哈希),其键是行。 next 将确保如果当前子句(这是第一个文件的事实)运行,则其他子句($0 in a)不会运行。当当前行在数组a 中有值时,$0 in a 将为真,因此只会显示两者中都存在的行。该顺序将是它们在第二个文件中出现的顺序。

【讨论】:

  • 是的,这确实有效(在我的示例中) - 即使我不明白如何!我会等一下,看看是否会出现基于 grep 的答案,或者会回来接受这个。谢谢。
  • @AdamKatz:非常感谢您在此处添加解释。我不知何故错过了 OP 的评论,忘记在这里添加一些解释。
【解决方案2】:

您需要做的就是将-x 标志添加到您的grep 查询中:

grep -Fxf list1.txt list2.txt > matches.txt

-x 标志将匹配限制为全行匹配(每个 PATTERN 变为 ^PATTERN$)。我不知道为什么你在-x 的尝试失败了。也许你把它放在-f之后,必须紧跟第一个文件?

【讨论】:

  • 是的,-Fxf-xFf 现在似乎都可以工作了。我确定我在发布之前以各种顺序组合尝试了这三个标志。那好吧。由于缺乏经验,我错过了 f 标志 必须 排在最后,以便 CL 中的下一项是文件名列表。谢谢!
  • 是的,grep 不会抱怨例如grep -Ffx list1.txt list2.txt 如果您有一个名为 x 的文件。
【解决方案3】:

一种非常简单直接的方法,不需要一个人用 grep 做各种疯狂的事情,如下所示

cat list1.txt list2.txt|grep match > matches.txt 不仅如此,它还更容易记住(特别是如果你经常使用 cat)。

【讨论】:

  • 如前所述,该命令行不起作用。使用list1.txtlist2.txt 中的数据,结果matches.txt 为空。 'match' 的作用尚不清楚 - 它是 grep 的标志还是其他命令。我的(OS 10.9.5)在man grep 中没有“匹配”条目,也没有将“匹配”识别为命令。这个 CL 似乎回答了与提出的问题不同的问题。
【解决方案4】:

grep -Fwf file1 file2 会逐字匹配!!

【讨论】:

    最近更新 更多