grep 与另一个文件 (4.8Gb) 中匹配的一个文件 (3.2Gb) 中的模式

Axe*_*son 8 linux grep large-files

我有两个文本文件。一种是带有姓名、电子邮件地址和其他字段的文本文件。一些线路来自file1

John:myemail@gmail.com:johnson123:22hey
Erik:thatwhatsup@gmail.com:johnson133:22hey
Robert:whatsup@gmail.com:johnson123:21hey
Johnnny:bro@gmail.com:johnson123:22hey
Run Code Online (Sandbox Code Playgroud)

另一个只包含电子邮件地址。示例来自file2

1@gmail.com
rsdoge@gmail.com
mynameiscurt@hotmail.com
myemail@gmail.com
Run Code Online (Sandbox Code Playgroud)

我希望输出是每个完整的行,file1file2. 例如,myemail@gmail.comis in file2,所以我想看到以下行file1

John:myemail@gmail.com:johnson123:22hey
Run Code Online (Sandbox Code Playgroud)

有没有一种简单的方法来搜索file1和输出与“电子邮件地址列表”匹配的行file2

我一直在搜索 HOURS,但我的 Google 搜索(和 StackOverflow 搜索)以及在命令行上的努力到目前为止还没有奏效。

我尝试过并认为可行的命令:

fgrep -f file2.txt file1.txt > matched.txt
grep -F -f ....
grep -F -x -f file1 file2 > common 
Run Code Online (Sandbox Code Playgroud)

等等,但他们都得到了grep memory exhausted- 我匹配的文件是 4.8GB ( file1) 和 3.2GB ( file2,仅包含电子邮件地址)。我假设这些命令会耗尽内存。我找到了一种方法find,我想可以更顺畅地执行命令,但没有让它起作用。

tldr ; 需要匹配file2file1如果有一行file2匹配 中的一行file1,输出它。文件很大,我需要一种安全的方法来不耗尽所有内存。

谢谢,为此搜索了一整天并进行了实验,不想放弃(5 小时以上)。

Cos*_*tas 7

操作大文件相当困难,但您可以分三步完成:

  1. 按第二个字段对file1排序

    sort -k2,2 -t: file1 >file1.sorted
    
    Run Code Online (Sandbox Code Playgroud)
  2. 排序文件2

    sort file2 >file2.sorted
    
    Run Code Online (Sandbox Code Playgroud)
  3. 通过电子邮件字段加入 2 个文件

    join -t: -2 2 file2.sorted file1.sorted -o 2.1,0,2.3,2.4 >matched.txt
    
    Run Code Online (Sandbox Code Playgroud)


Kus*_*nda 5

我正在提交这个问题的第二个答案(这是一个有趣的问题)。这个与我的 SQLite 解决方案完全不同,也与开始出现的看起来很有前途的sort+join解决方案完全不同:

使用你的初始方法grep -f,但实际上减少了一点问题。让我们使用 将“查询文件”拆分file2为可管理的块split

split实用程序能够根据行数将文件拆分为多个较小的文件。

平均行长为 20 个字符的 3.2 Gb 文件大约有 172,000,000 行(除非我犯了算术错误)。拆分为 2000 个文件,每个文件 85000 行是可行的。

所以,

$ mkdir testing
$ cd testing
$ split -l 85000 -a 4 ../file2
Run Code Online (Sandbox Code Playgroud)

-a 4选项告诉split在首字母之后使用四个字符x来为新文件创建文件名。该文件将被称为xaaaaxaaab等等。

然后grep -f在这些上运行原件:

for f in x????; do
  grep -F -f "$f" ../file1
done
Run Code Online (Sandbox Code Playgroud)

可能使得grep能够在内存中保存现在更小的查询模式集。

更新:使用 145,526,885 行,用于split -l 72000 -a 4创建大约 2000 个文件。

testing每次尝试创建一组新的拆分文件时,请记住清除目录。

请注意,此答案中的拆分文件可单独用作您对此问题可能获得的任何其他答案的输入。


Jim*_*Jim 1

像这样的东西会起作用,但我不确定这是否是一个好主意,具体取决于您的用例(未经测试):

while read f2line
do
  f1=$(grep $line file1)

  [[ ! -z $f1 ]] && echo $f1line 
done < file2
Run Code Online (Sandbox Code Playgroud)

如果您想要更多的单行方法,另一种可能的解决方案(下面快速测试):

grep . file2 | xargs -i^ grep ^ file1
Run Code Online (Sandbox Code Playgroud)

结果是:

root@7Z233W1 (/tmp)# cat f1
John:myemail@gmail.com:johnson123:22hey
Erik:thatwhatsup@gmail.com:johnson133:22hey
Robert:whatsup@gmail.com:johnson123:21hey
Johnnny:bro@gmail.com:johnson123:22hey

root@7Z233W1 (/tmp)# cat f2
1@gmail.com
rsdoge@gmail.com
mynameiscurt@hotmail.com
myemail@gmail.com

root@7Z233W1 (/tmp)# grep . f2 | xargs -i^ grep ^ f1
John:myemail@gmail.com:johnson123:22hey
Run Code Online (Sandbox Code Playgroud)