Разделить файл по шаблону, сохраняя только фрагменты, содержащие второй шаблон

В предыдущем ответе я нашел следующий awk-скрипт для разделения больших файлов на более мелкие части на основе шаблона (заменяя «строку заголовка» другим шаблоном). Тем не менее, мне нужно принять его еще больше, поскольку могут быть созданы миллионы частей, но если я смогу снова фильтровать их, он получит то, что мне нужно.

awk ' /header-line/ {++part} {print >sprintf("part-%03d.txt", part)} ' 

Возможно ли допросить каждую «часть» до или после того, как она будет записана, чтобы проверить, существует ли какой-то шаблон в части и только написать эту часть на соответствие для дополнительного шаблона.

В качестве примера, начальными критериями будут «ID:» (верхняя строка выше). Затем я хочу искать каждую «часть», созданную для определенного имени метода; назовите его «searchForThisMethod» в качестве строки для поиска, которая может быть в разных местах в части.

Пример ввода:

 ID: 1 bb bb bb bb secondaryCheck ID: 2 b b b b b b b b ID: 3 h h h h h secondaryCheck g g g g 

  • Условное предложение if в awk
  • Как обновить даты (на 30 дней) в файлах, идущих в это конкретное место в unix?
  • Разбор сложного текстового файла с использованием команд Unix
  • Сценарий оболочки и добавление больших значений в проблему с ограниченным файлом
  • как создать файл данных со столбцом даты от дня1 до дня?
  • что делает getline внутри awk?
  • лучший способ разделить огромные файлы на основе поля, когда awk слишком медленный
  • Что означает vRS = "\ n20" в командной строке gawk?
  • One Solution collect form web for “Разделить файл по шаблону, сохраняя только фрагменты, содержащие второй шаблон”

    Вы можете разбить файл, а затем запустить grep -q some_method на каждой части и удалить его, если false, например

     for file in part-*.txt; do grep -q some_method "$file" if [ $? -ne 0 ] then rm "$file" fi done 

    или
    используйте два прохода – удалив из ввода «части», которые содержат some_method затем разделили результат, например, с помощью sed для первого прохода и вашего awk кода для второго прохода:

     sed -e '1{h;d;}' -e '/ID/!{H;$!d;}' -e 'x;/some_method/!d' infile | \ awk '/ID/{++part}{print > sprintf("part-%03d.txt", part)}' 

    sed копирует 1-ю строку над старым буфером h и d eletes добавляет каждую строку, которая не соответствует ID в старый буфер H , удаляет ее, если это не последняя строка, а e x изменяет буферы на строках, которые соответствуют ID удаляющему шаблон если он не содержит some_method . Затем результат передается на awk . Если вы получаете too many open files ошибок too many open files вам придется close() файлы:

     sed -e '1{h;d;}' -e '/ID/!{H;$!d;}' -e 'x;/some_method/!d' infile | \ awk '/ID/{++part}{close(fn);fn=sprintf("part-%03d.txt", part);print >> fn}' 

    или, если вы используете gnu / anything, вы можете использовать csplit вместо awk :

     sed '1{h;d};/ID/!{H;$!d};x;/some_method/!d' infile | \ csplit -f 'part-' -b '%03d.txt' -sz - /ID/ '{*}' 
    Linux и Unix - лучшая ОС в мире.