【问题标题】:Combine grep -f and awk结合 grep -f 和 awk
【发布时间】:2015-03-23 22:40:11
【问题描述】:

我正在使用两个命令:

awk '{ print $2 }' SomeFile.txt > Pattern.txt

grep -f Pattern.txt File.txt

使用第一个命令,我创建了一个理想模式列表。使用第二个命令,我提取 File.txt 中与 Pattern.txt 中的行匹配的所有行

我的问题是,有没有办法在管道中结合 awk 和 grep,这样我就不必生成中间的 Pattern.txt 文件?

谢谢!

【问题讨论】:

  • 在使用“模式”一词时要非常小心,因为该术语没有特定含义,因此可以解释。要清楚 - 你是在谈论匹配字符串或正则表达式或其他东西吗?您想匹配整行/单词还是部分行/单词?显示一些示例输入和预期输出。

标签: awk grep


【解决方案1】:

您可以在一次 awk 调用中完成这一切:

awk 'NR==FNR{a[$2];next}{for(i in a)if($0~i)print}' Somefile.txt File.txt

从第一个文件的第二列填充数组a 中的键。 NR==FNR 标识第一个文件(总记录数等于该文件的记录数)。 next 跳过第一个文件的第二个块。

在第二个块中,循环遍历数组中的所有键,如果该行与其中任何一个匹配,则打印它。为避免在匹配多个模式时多次打印该行,您也可以在此处添加next,即{for(i in a)if($0~i){print;next}}

如果“模式”实际上是固定的字符串,那就更简单了:

awk 'NR==FNR{a[$2];next}$0 in a' Somefile.txt File.txt

【讨论】:

  • 最好使用awk 来完成它可以做的事情并完全保存grep 进程! +1
【解决方案2】:

如果你的shell支持,你可以使用process substitution:

grep -f <(awk '{ print $2 }' SomeFile.txt) File.txt

bashzsh 会支持,其他人可能也会支持,但未测试。


上述更简单且所有 shell 都支持的方法是使用管道:

awk '{ print $2 }' SomeFile.txt | grep -f - File.txt

- 用作-f 的参数。 -在这里有特殊含义,代表stdin。感谢Tom Fenech 提及!

【讨论】:

  • 这看起来比 awk +1 中的所有都好
  • 如果不支持进程替换,我想你可以做awk '{print $2}' SomeFile.txt | grep -f - File.txt
  • @JID 在许多其他情况下也很方便,例如diff &lt;(command) &lt;(sleep 1;command) 或其他......
  • @Yorgos 喜欢“单衬”的问题是您最终会得到一系列深受喜爱但一次性使用的单衬,并且必须为下一个要求新的单衬您遇到的问题,而不是一次只学习一个问题/答案如何在 awk 中编写通用文本处理代码,这样您也可以解决所有未来的问题。
  • 请注意,有一个bug in grep -f 在您有超过一百个查询时会使这个非常慢full awk solution 不会受此影响。纯文本 awk 解决方案(在同一答案中)也比使用 grep -xFf 快得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-26
  • 1970-01-01
  • 1970-01-01
  • 2021-05-15
  • 1970-01-01
  • 2016-10-10
  • 1970-01-01
相关资源
最近更新 更多