优化此脚本以匹配一个txt文件的行与另一个

时间:2013-06-11 19:21:53

标签: bash optimization scripting large-files

好吧所以我充其量只是一个bash脚本的新手,但是我在昨晚深夜写了这个非常小的脚本来获取一个相当大的文本文件(~300,000行)的每一行的前40个字符并搜索更大的匹配的文本文件(~220万行),然后将所有结果输出到匹配行中的新文本文件中。

所以脚本看起来像这样:

#!/bin/bash
while read -r line
  do
  match=${line:0:40}
  grep "$match" large_list.txt
done <"small_list.txt"

然后通过这样调用脚本

$ bash my_script.sh > outputfile.txt &

这给了我2个列表之间的所有共同元素。现在这一切都很好,并且慢慢起作用。但是我在m1.smalll ec2实例上运行它并且足够公平(对此进行处理是糟糕的,我可以启动一个更大的实例来处理所有这些或者在我的桌面上执行并上传文件)。但是我宁愿学习一种更有效的方法来完成同样的任务,但我似乎无法想象这一点。任何关于如何最好地解决这个问题,或者更有效地完成任务的花絮都会非常感激

让你知道这是多么缓慢的工作我大约10个小时前启动了脚本,我在所有比赛的大约10%的路上。

此外,我还没有使用bash,因此其他语言的脚本是公平的游戏。我在S.O.上找到专业人士。可以很容易地改善我的岩石锤子的方法

编辑:添加有关数据的输入和输出以及morre信息

 input: (small text file)
  8E636C0B21E42A3FC6AA3C412B31E3C61D8DD062|Vice S01E09 HDTV XviD-FUM[ettv]|Video TV|http://bitsnoop.com/vice-s01e09-hdtv-xvid-fum-ettv-q49614889.html|http://torrage.com/torrent/36A02E282D49EB7D94ACB798654829493CA929CB.torrent
  3B9403AD73124A84AAE12E83A2DE446149516AC3|Sons of Guns S04E08 HDTV XviD-FUM[ettv]|Video TV|http://bitsnoop.com/sons-of-guns-s04e08-hdtv-xvid-fum-e-q49613491.html|http://torrage.com/torrent/3B9403AD73124A84AAE12E83A2DE446149516AC3.torrent
  C4ADF747050D1CF64E9A626CA2563A0B8BD856E7|Save Me S01E06 HDTV XviD-FUM[ettv]|Video TV|http://bitsnoop.com/save-me-s01e06-hdtv-xvid-fum-ettv-q49515711.html|http://torrage.com/torrent/C4ADF747050D1CF64E9A626CA2563A0B8BD856E7.torrent
  B71EFF95502E086F4235882F748FB5F2131F11CE|Da Vincis Demons S01E08 HDTV x264-EVOLVE|Video TV|http://bitsnoop.com/da-vincis-demons-s01e08-hdtv-x264-e-q49515709.html|http://torrage.com/torrent/B71EFF95502E086F4235882F748FB5F2131F11CE.torrent

 match against (large text file)

  86931940E7F7F9C1A9774EA2EA41AE59412F223B|0|0
  8E636C0B21E42A3FC6AA3C412B31E3C61D8DD062|4|2|20705|9550|21419
  ADFA5DD6F0923AE641F97A96D50D6736F81951B1|0|0
  CF2349B5FC486E7E8F48591EC3D5F1B47B4E7567|1|0|429|428|22248
  290DF9A8B6EC65EEE4EC4D2B029ACAEF46D40C1F|1|0|523|446|14276
  C92DEBB9B290F0BB0AA291114C98D3FF310CF0C3|0|0|21448


 Output: 
  8E636C0B21E42A3FC6AA3C412B31E3C61D8DD062|4|2|20705|9550|21419

其他说明:所以基本上有一个哈希值,它是输入文件的第一个40个字符(一个文件我已经将大小减小到原始的15%左右,对于这个文件中的每一行,SO都有一个大的哈希值文本文件(我正在匹配)与一些相应的信息现在它是我想要写入新文件的较大文件中的行,以便最终我在较小的文本中具有1:1的所有比例的比率file到我的output_file.txt 在这种情况下,我显示匹配的输入的第一行(较大文件的第2行),然后写入输出文件

2 个答案:

答案 0 :(得分:2)

this answer采用

awk解决方案:

awk -F"|" 'NR==FNR{a[$1]=$2;next}{if (a[$1]) print}' small.txt large.txt

答案 1 :(得分:1)

一些蟒蛇救援。

我使用以下代码段创建了两个文本文件:

#!/usr/bin/env python

import random
import string

N=2000000
for i in range(N):
    s = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(40))
    print s + '|4|2|20705|9550|21419'

一个300k和一个2M行这给了我以下文件:

$ ll
-rwxr-xr-x 1  210 Jun 11 22:29 gen_random_string.py*
-rw-rw-r-- 1 119M Jun 11 22:31 large.txt
-rw-rw-r-- 1  18M Jun 11 22:29 small.txt

然后我将一行从small.txt附加到large.txt的末尾,以便我有一个匹配的模式

然后再多一些python:

#!/usr/bin/env python

target = {}

with open("large.txt") as fd:
    for line in fd:
        target[line.split('|')[0]] = line.strip()

with open("small.txt") as fd:
    for line in fd:
        if line.split('|')[0] in target:
            print target[line.split('|')[0]]

一些时间:

$ time ./comp.py 
3A8DW2UUJO3FYTE8C5ESE25IC9GWAEJLJS2N9CBL|4|2|20705|9550|21419

real    0m2.574s
user    0m2.400s
sys 0m0.168s

$ time awk -F"|" 'NR==FNR{a[$1]=$2;next}{if (a[$1]) print}' small.txt large.txt
3A8DW2UUJO3FYTE8C5ESE25IC9GWAEJLJS2N9CBL|4|2|20705|9550|21419

real    0m4.380s
user    0m4.248s
sys 0m0.124s

更新

为了节省内存,请以其他方式进行字典查找

#!/usr/bin/env python

target = {}

with open("small.txt") as fd:
    for line in fd:
        target[line.split('|')[0]] = line.strip()

with open("large.txt") as fd:
    for line in fd:
        if line.split('|')[0] in target:
            print line.strip()