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

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

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

文件1.txt:

Hey123
Johnson
Hanny123
Fanny

(文件 1 为 240MB - 20.000.000 行)

文件2.txt:

Gromy123:hannibal
Hey123:groll
Hanny123:tronda9
Kroppsk:football23

(文件 2 为 1.4GB - 69.000.000 行)

预期的匹配行输出:

Hanny123:tronda9
Hey123:groll

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

答案1

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

join -t : File1.txt File2.txt

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

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

<File1.txt tr -d '\r' | join -t : - File2.txt

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

join -t : <(sort File1.txt) <(sort File2.txt)

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

sort File2.txt | { sort File1.txt | join -t : /dev/fd/0 /dev/fd/3; } 3<&1

如果您需要保留原始顺序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

答案2

如果您有 2GB 的可用 RAM,请尝试

awk -F: 'NR==FNR { n[$0]++ ; next}; $1 in n ' file1 file2 > file3

答案3

一个可能的解决方案(这当然适用于您的小例子):

#!/bin/bash

# because File2.txt is bigger, it gets the main loop.
# read each line of File2.txt
while read string; do
    # read each line of File1.txt
    while read string2; do
    # check match, and write if needed.
    if [[ $string == *"$string2"* ]]; then
        echo $string >> match_output.txt
        echo "wrote "$string" to match_output.txt..."
    fi
    done < File1.txt
done < File2.txt

相关内容