【问题标题】:Finding existence each string in file1 in another file在另一个文件中查找 file1 中的每个字符串是否存在
【发布时间】:2023-03-09 10:14:01
【问题描述】:

以下是两个文件的内容,

文件:1

257054
256986
257144

文件:2

257054|Guestroom|http://397_b.jpg|350|350||http://397/hotels/2000000/1330000/1321300/1321278/1321278_397_t.jpg|0
257057|Guestroom|http://398_b.jpg|350|350||http://398/hotels/2000000/1330000/1321300/1321278/1321278_398_t.jpg|0

我需要一个 Bash 命令来比较两个文件,并且输出只包含

257054|Guestroom|http://397_b.jpg|350|350||http://397/hotels/2000000/1330000/1321300/1321278/1321278_397_t.jpg|0

我可以使用正常的 for 循环迭代,但速度很慢。我需要一些使用 awk 或 sed 的快速处理解决方案。

【问题讨论】:

  • 试过grep -f file1 file2 ???虽然不是一个强大的解决方案
  • 我试过没有返回任何输出
  • 您可能有一个没有 -f 标志的 grep 版本(尽管我认为这是非常标准的),但该解决方案可以用作 @PS。描述
  • 部分匹配还是完全匹配?在一个领域或几个领域或整条线上?正则表达式或字符串比较?具体一点。
  • 谢谢 PS,我找到了原因,file1 中有一些元空间阻止了这个 grep 命令的功能。现在它工作正常,但我的文件包含近 10 百万个条目,这使得这种方法的性能密集度较低。

标签: shell awk sed grep


【解决方案1】:

您可以在Awk 中一次性完成此操作,

awk 'BEGIN{FS=OFS="|"}FNR==NR{file1[$0]; next}$1 in file1' file1 file2

file1 上将内容散列到数组 file1 的索引中,并在 file2 上打印 $1seen 中的那些行。

【讨论】:

  • 感谢 Inian,这种方法运行良好且速度非常快。
  • @Raghavan:很高兴你发现它很有用!
【解决方案2】:

如果file1的内容只能出现在file2的首位,可以使用fgrep

$ cat file1
257054
256986
257144
$ cat file2
257054|Guestroom|http://397_b.jpg|350|350||http://397/hotels/2000000/1330000/1321300/1321278/1321278_397_t.jpg|0
257057|Guestroom|http://398_b.jpg|350|350||http://398/hotels/2000000/1330000/1321300/1321278/1321278_398_t.jpg|0
$ fgrep -f file1 file2
257054|Guestroom|http://397_b.jpg|350|350||http://397/hotels/2000000/1330000/1321300/1321278/1321278_397_t.jpg|0

请注意,您可以将 fgrep 替换为 grep -F:两者都是 POSIX。使用 fgrep 模式将 file1 的内容视为一组文字模式,每行一个。在没有-F 的情况下尝试grep -f 不会给你想要的结果。

如果file1 中的数字可能存在于file2 中除行首之外的其他位置,那么您可以通过将grep 与例如sed 结合使用来创建更明确的匹配:

grep -f <(sed 's/.*/^&|/g' file1) file2

这与来自file1 的数字匹配仅当它们出现在行首并后跟竖线时(|

【讨论】:

  • @EdMorton 如果有awk,则不需要 grep, join, paste, sed, nl, @987654342 @,还有很多很多。一种神器的存在并不意味着必须使用该神器来解决所有可能的问题。尽管如此,我还是把它做成了 grep+sed,这是一个更“合理”的组合。
  • The presence of one god tool does not obligate one to use said god tool for all possible problems. 我没有建议。您列出的所有工具都是非常好的工具。我说如果你使用“上帝工具”,你不需要添加“管道工工具”来帮助上帝安装你的厨房水槽。如果您使用的是 grep+sed,则应该使用 awk。
  • 是的,但没有什么强迫你编写难以理解的 awk。改为编写易于理解的 awk,并获得该方法带来的清晰性、稳健性、可移植性、效率等优势。如果您认为您的 grep+sed+shell 方法在数量上比 @Inian's awk script 更容易理解,您在做梦!无论如何,我们将无法继续这样做 - 祝你编程好运。
  • 需要帮助使用 grep 解决此问题的人可能无法维护 awk 解决方案。使用哪种工具取决于工具能力和用户能力。
  • grep -w(全字)开关可以稍微简化代码:grep -w -f &lt;(sed s/^/^/ file1) file2
【解决方案3】:

你也可以使用join:

$ join -t \| f1 f2
257054|Guestroom|http://397_b.jpg|350|350||http://397/hotels/2000000/1330000/1321300/1321278/1321278_397_t.jpg|0

man join 教育我们:

NAME
       join - join lines of two files on a common field

SYNOPSIS
       join [OPTION]... FILE1 FILE2

       -t CHAR
              use CHAR as input and output field separator

【讨论】:

猜你喜欢
  • 2012-12-07
  • 2016-12-12
  • 1970-01-01
  • 2011-03-24
  • 2018-05-28
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多