Как я могу объединить «Поиск нескольких строк (шаблонов)» с «Печать строк после попадания» в строке/поиске и вывести общий файл?

Я использую версию grep для Windows «GNU Grep».

      syntax: grep [OPTIONS] PATTERN [FILE...]

Как я могу комбинировать разные варианты с разными узорами?

Обе перечисленные здесь линии работают самостоятельно. Но объединить их мне пока не удалось.

      grep -i -a -h -E "word1|word2" INfilename.log* > "OUTfilename.txt"
grep -i -a -h -A 6 "word3" INfilename.log* > "OUTfilename.txt"

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

      2023-07-29 11:31:01 bla something bla
2023-07-29 11:31:02 bla word1 bla
2023-07-29 11:31:03 bla something bla
2023-07-29 11:31:04 bla word2 bla
2023-07-29 11:31:05 bla something bla
2023-07-29 11:31:06 bla word3 bla
2023-07-29 11:31:07 bla something bla
2023-07-29 11:31:08 bla something bla
2023-07-29 11:31:09 bla something bla
2023-07-29 11:31:10 bla something bla
2023-07-29 11:31:11 bla something bla
2023-07-29 11:31:12 bla something bla
2023-07-29 11:31:13 bla something bla

Результат должен выглядеть так:

      2023-07-29 11:31:02 bla word1 bla
2023-07-29 11:31:04 bla word2 bla
2023-07-29 11:31:06 bla word3 bla
2023-07-29 11:31:07 bla something bla
2023-07-29 11:31:08 bla something bla
2023-07-29 11:31:09 bla something bla
2023-07-29 11:31:10 bla something bla
2023-07-29 11:31:11 bla something bla
2023-07-29 11:31:12 bla something bla

1 ответ

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

Следующий код хорошо работает с вашим примером:

      #!/bin/awk -f
FNR==1 { n=-1 }
/word1|word2/ && n<0 { n=0 }
/word3/       && n<6 { n=6 }
n>=0 { n--; print }

Примечания:

  • Я использую Linux и не использую Windows. Код представляет собой скрипт для Linux. Если вы можете работать в Windows, вы, по крайней мере, сможете запустить код, сохранив его в файле и вызвавawk -f path_to_the_file. Я думаю, эта команда также будет работать:

            awk "FNR==1 { n=-1 } /word1|word2/ && n<0 { n=0 } /word3/ && n<6 { n=6 } n>=0 { n--; print }"
    
  • Сценарий (или команду) можно вызвать с одним или несколькими путями в качестве дополнительных аргументов для указания файлов, из которых нужно читать входные данные; так что это должно быть возможно:

            awk … INfilename.log*
    

    (по крайней мере, это работает в Linux). Обратите внимание, что когда наш код переходит к следующему файлу, он намеренно сбрасывается, поэтому поведение имитирует-A 6вызваныword3ближе к концу одного файла не распространяется на следующий файл. Если вы хотите обрабатывать содержимое многих файлов как один поток, сначала объедините файлы (в Linux:cat … | awk …).

  • Вы можете легко добавить больше регулярных выражений со своими собственными значениями, например/word4/ && n<3 { n=3 }. Обратите внимание на значение, которое вы бы использовали сgrep's-A(здесь3) появляется в двух местах; Я предпочел KISS DRY.

  • Если линия соответствует более чем одному шаблону, то самый большойnВыиграет.

  • Соответствующая линия внутри того, чтоman grepвызовы «замыкающего контекста» могут только сделать контекст длиннее, но не короче. Другими словами, если вы представляете файлы как упорядоченные наборы строк, из нашего кода вы получите объединение всех совпадающих строк и завершающих контекстов.

  • grep -Aможет печатать разделители групп. Ваш пример их не содержит, поэтому нашawkкод не беспокоит.

  • Сопоставление с образцом в нашем коде чувствительно к регистру. Я заметил, что ты использовалgrep -i. Посмотрите этот ответ и при необходимости измените код (замените/word1|word2/сtolower($0) ~ /word1|word2/и т. д.). Обратите внимание, что вы можете настроить или нет отдельно для каждого шаблона.

Другие вопросы по тегам