Оптимизация этого скрипта для соответствия строк одного текстового файла другому
Итак, я в лучшем случае новичок в написании сценариев bash, но вчера вечером я написал этот очень маленький сценарий, чтобы взять первые 40 символов каждой строки довольно большого текстового файла (~300000 строк) и искать в гораздо большем текстовом файле для совпадений (~2,2 миллиона строк), а затем выведите все результаты в соответствующие строки в новый текстовый файл.
поэтому скрипт выглядит так:
#!/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 &
и это дает мне все общие элементы между двумя списками. Теперь это все хорошо, медленно работает. но я запускаю это на экземпляре m1.smalll ec2 и достаточно справедливо (процесс на этом дерьме, и я мог бы раскрутить больший экземпляр для обработки всего этого или сделать это на моем рабочем столе и загрузить файл). Однако я предпочел бы изучить более эффективный способ выполнения той же задачи, однако я не могу понять это. Любые лакомые кусочки о том, как лучше всего сделать это или выполнить задачу более эффективно, будут очень и очень признательны
чтобы дать вам представление о том, насколько медленно это работает, я запустил сценарий около 10 часов назад, и я прошел примерно 10% всех матчей.
Кроме того, я не настроен на использование bash, поэтому скрипты на других языках являются честной игрой. Я полагаю, что профессионалы на SO могут легко улучшить мой рок за счет молотка.
редактировать: добавляя входные и выходные данные и более подробную информацию о данных
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% от исходного, поэтому для каждой строки в этом файле есть хеш в текстовом файле большего размера (что я сопоставляю) с некоторой соответствующей информацией, теперь это строка в файле большего размера, которую я хотел бы записать в новый файл, чтобы в итоге у меня было соотношение 1:1 всех вещей в меньшем текстовом файле к моему output_file.txt В этом случае я показываю первую строку сопоставляемого ввода (строка 2 большего файла), а затем записываю в выходной файл
2 ответа
awk
Решение, принятое из этого ответа:
awk -F"|" 'NR==FNR{a[$1]=$2;next}{if (a[$1]) print}' small.txt large.txt
Какой -то питон на помощь.
Я создал два текстовых файла, используя следующий фрагмент:
#!/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()