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 耗尽。希望得到一些帮助,我如何解决这个问题,这么大的文件。
如果文件已排序(您发布的示例是),那么它就像
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)