Как я могу объединить «Поиск нескольких строк (шаблонов)» с «Печать строк после попадания» в строке/поиске и вывести общий файл?
Я использую версию 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/
и т. д.). Обратите внимание, что вы можете настроить или нет отдельно для каждого шаблона.