比较两个文件并打印匹配项 - 大文件

Axe*_*son 4 grep awk text-processing

我需要比较 2 个文件并打印匹配的行。如果 file1 用户名在 file2 (字段 1)中,我想将其打印到新的匹配文件中。

文件1.txt:

Hey123
Johnson
Hanny123
Fanny
Run Code Online (Sandbox Code Playgroud)

(文件 1 为 240MB - 20.000.000 行)

文件2.txt:

Gromy123:hannibal
Hey123:groll
Hanny123:tronda9
Kroppsk:football23
Run Code Online (Sandbox Code Playgroud)

(file2 是 1.4GB - 69.000.000 行)

预期的匹配行输出:

Hanny123:tronda9
Hey123:groll
Run Code Online (Sandbox Code Playgroud)

我已经尝试了 4 个小时没有成功。两个文件都已排序,我尝试过 join + 无数的 grep / awk 命令。我的大问题是 RAM 耗尽。希望得到一些帮助,我如何解决这个问题,这么大的文件。

Gil*_*il' 5

如果文件已排序(您发布的示例是),那么它就像

join -t : File1.txt File2.txt
Run Code Online (Sandbox Code Playgroud)

join将连接字段相等的两个文件中的行配对。默认情况下,join字段是第一个字段,除了join字段不重复之外,其他字段都是按顺序输出的,跳过不可配对的行,这正是你想要的。

请注意,如果文件具有Windows 行尾,它们在 Unix 系统下会出现在每行末尾有一个额外的回车符。CR 大多在视觉上是不可见的,但就join和其他文本工具而言,它和其他任何一个字符一样,这​​意味着File1.txt所有字段都以 CR 结尾,而所有字段都以 CR 结尾,而其中的字段File2.txt则不匹配,因此它们不匹配. 您需要剥离 CR,至少在File1.txt.

<File1.txt tr -d '\r' | join -t : - File2.txt
Run Code Online (Sandbox Code Playgroud)

您确实需要对文件进行排序。如果不是,那么 ksh/bash/zsh,您可以使用进程替换。(tr -d '\r' |需要时添加。)

join -t : <(sort File1.txt) <(sort File2.txt)
Run Code Online (Sandbox Code Playgroud)

在普通 sh 中,如果您的 Unix 变体具有/dev/fd(大多数都具有),您可以使用它来通过两个文件描述符来管道传输两个程序的输出。

sort File2.txt | { sort File1.txt | join -t : /dev/fd/0 /dev/fd/3; } 3<&1
Run Code Online (Sandbox Code Playgroud)

如果您需要保留的原始顺序File1.txt并且不按连接字段排序,则添加行号以记住原始顺序,按连接字段排序,连接,按行号排序并去除行号。(如果你想保留另一个文件的顺序,你可以做类似的事情。)

<File1.txt nl -s : |
sort -t : -k 2 |
join -t : -1 2 - <(sort File2.txt) |
sort -t : -k 2,2n |
cut -d : -f 1,3
Run Code Online (Sandbox Code Playgroud)