在一个文件中查找不在另一个文件中的 ID

Ava*_*eka 9 command-line files text-processing

我有两个文件:

abc.txt

abcd
xyz
pqrs
Run Code Online (Sandbox Code Playgroud)

文件.txt

zzon
mkno
abcd
Run Code Online (Sandbox Code Playgroud)
  • 我想检查文件mno.txt 中是否存在“abcd” 。
  • 如果 "abcd" 在abc.txt在第一位,则它也没有必要在mno.txt在第一位
  • 两个文件中都有数千个这样的 id。
  • 我还想检查mno.txt中有多少 id 不在abc.txt 中

我怎样才能做到这一点 ?

Oli*_*Oli 19

如果您的目标是找到常见或不常见的线条,comm这将是我的首选命令。

它比较两个文件并在三列中分别显示文件 1 独有的行、文件 2 独有的行以及出现在两个文件中的行。您也可以传递它标志来抑制任何此输出。例如,comm -1 file1 file2将抑制第一列,file1 独有的东西。comm -12 file1 file2只会显示两个文件中的内容。

有一个很大的警告:必须对输入进行排序。我们可以解决这个问题。

这将向您显示 abc 中不在 mno 中的所有内容:

comm -23 <(sort abc.txt) <(sort mno.txt)
Run Code Online (Sandbox Code Playgroud)

您可以将其输入wc -l以进行计数。


comm同意的原因是,一旦文件被排序,并排比较在计算上非常简单。如果您正在处理数百万个这样的问题,那将会有所不同。

这可以通过几个模拟文件来演示。我有一台相当快的计算机,所以为了显示方法之间的差异,我需要一个相当庞大的样本集。我已经为每个文件处理了 1000 万个 10 字符的字符串。

$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > abc.txt
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > mno.txt

$ time comm -23 <(sort abc.txt) <(sort mno.txt) | wc -l
... 0m10.653s

$ time grep -Fcxv -f abc.txt mno.txt
... 0m23.920s

$ time grep -Fcwv -f abc.txt mno.txt
... 0m40.313s

$ time awk 'NR==FNR{a[$0]++};NR!=FNR && a[$0]' abc.txt  mno.txt | wc -l
... 0m12.161s
Run Code Online (Sandbox Code Playgroud)

排序是我的大部分时间。如果我们假装 abc.txt 是静态的,我们可以对它进行预排序,这样可以更快地进行未来的比较:

$ sort abc.txt abc-sorted.txt
$ time comm -23 abc-sorted.txt <(sort mno.txt) | wc -l
... 0m7.426s
Run Code Online (Sandbox Code Playgroud)

您可能会查看这些并认为几秒钟无关紧要,但我必须强调这些是在高端机器上运行的。如果您想在(例如)Raspberry Pi 3 上执行此操作,您将看到周转速度要慢得多,并且差异将增加到实际上很重要的程度。


Rav*_*ina 7

获取列表:

grep -Fwf abc.txt mno.txt
Run Code Online (Sandbox Code Playgroud)

它给你类似的东西:

abcd
abcd
zef
Run Code Online (Sandbox Code Playgroud)

如果你只想获得一个唯一的列表,那么使用它:

grep -Fwf abc.txt mno.txt | sort | uniq
Run Code Online (Sandbox Code Playgroud)

并获得计数:

grep -Fcwv -f abc.txt mno.txt
Run Code Online (Sandbox Code Playgroud)
  • -F 意思是:将 PATTERN 解释为固定字符串列表而不是正则表达式。
  • -f从 FILE 中获取模式,这将是abc.txt.
  • 我们寻找mno.txt模式
  • -c 计算匹配的数量
  • -w仅查找“整个单词”:匹配的子字符串必须位于行首,或者前面是非单词组成字符。同样,它必须位于行尾或后跟非单词组成字符。单词组成字符是字母、数字和下划线。
  • -v 反向搜索