Grep для нескольких выходных файлов - PullRequest
3 голосов
/ 03 декабря 2011

У меня есть один огромный файл (более 6 ГБ) и около 1000 шаблонов.Я хочу извлечь строки, соответствующие каждому шаблону, в отдельный файл.Например, мои шаблоны:

1
2

мой файл:

a|1
b|2
c|3
d|123

В качестве вывода я хотел бы иметь 2 файла:

1:

a|1
d|123

2:

b|2
d|123

Я могу сделать это, многократно извлекая файл, но это неэффективно для 1000 образцов и большого файла.Я также попробовал что-то вроде этого:

grep -f pattern_file huge_file

, но он сделает только 1 выходной файл.Я не могу отсортировать мой огромный файл - это занимает много времени.Может быть, AWK это сделает?

Ответы [ 5 ]

5 голосов
/ 03 декабря 2011
awk -F\| 'NR == FNR {
  patt[$0]; next
  }
{
  for (p in patt)
    if ($2 ~ p) print > p
  }' patterns huge_file

В некоторых реализациях awk вы можете достичь максимального количества открытых файлов.Дайте мне знать, если это так, чтобы я мог опубликовать альтернативное решение.

PS: в этой версии одновременно будет открыт только один файл:

awk -F\| 'NR == FNR {
  patt[$0]; next
  }
{
  for (p in patt) {
    if ($2 ~ p) print >> p
    close(p)
    }
  }' patterns huge_file
4 голосов
/ 10 сентября 2013

Вы можете сделать это (если я понимаю проблему), используя bash «процесс подстановки», например, рассмотрите следующие примеры данных:

$ cal -h
   September 2013     
Su Mo Tu We Th Fr Sa  
 1  2  3  4  5  6  7  
 8  9 10 11 12 13 14  
15 16 17 18 19 20 21  
22 23 24 25 26 27 28  
29 30 

Тогда выборочные строки могут быть grep d для разных выходных файлов в одной команде как:

$ cal -h \
    | tee >( egrep '1'    > f1.txt ) \
    | tee >( egrep '2'    > f2.txt ) \
    | tee >( egrep 'Sept' > f3.txt ) 

В этом случае каждый grep обрабатывает весь поток данных (что может или не может быть тем, что вы хотите: это может не сэкономить много времени по сравнению с просто выполнением одновременных grep процессов):

$ more  f?.txt
::::::::::::::
f1.txt
::::::::::::::
   September 2013     
 1  2  3  4  5  6  7  
 8  9 10 11 12 13 14  
15 16 17 18 19 20 21  
::::::::::::::
f2.txt
::::::::::::::
   September 2013     
 1  2  3  4  5  6  7  
 8  9 10 11 12 13 14  
15 16 17 18 19 20 21  
22 23 24 25 26 27 28  
29 30                 
::::::::::::::
f3.txt
::::::::::::::
   September 2013     
1 голос
/ 03 декабря 2011

Это может работать для вас (хотя sed может быть не самым быстрым инструментом!):

 sed 's,.*,/&/w &_file,' pattern_file > sed_file

Затем запустите этот файл с источником:

 sed -nf sed_file huge_file

Я сделалкраткий тест и GNU sed version 4.1.5, который я использовал, легко открывали 1000 файлов, но ваша система Unix вполне может иметь меньшие ограничения.

0 голосов
/ 27 марта 2014

У меня была эта потребность, поэтому я добавил возможность в свою собственную копию grep.c, которая случайно оказалась у меня в руках. Но это просто пришло мне в голову: если основная цель состоит в том, чтобы избежать нескольких проходов через огромный вход, вы можете запустить egrep один раз для огромного ввода, чтобы найти любой из ваших паттернов (что, я знаю, не то, что вы хотите), и перенаправить его вывод в промежуточный файл, затем выполнить несколько проходов по этому промежуточному файлу, один раз для каждого шаблона, перенаправляя каждый раз в другой конечный файл.

0 голосов
/ 03 декабря 2011

Grep не может выводить совпадения разных шаблонов в разные файлы.Tee может перенаправить свой ввод в несколько пунктов назначения, но я не думаю, что это то, что вам нужно.

Либо используйте несколько команд grep, либо напишите программу, чтобы сделать это на Python или на любом другом языке, который вам нравится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...