как я могу изменить приведенный ниже код, чтобы напечатать строки, которые соответствуют следующим критериям, но только если оба условия верны?
строки, которые мне нужно извлечь, должны соответствовать этому :
напечатайте только строку, соответствующую шаблону, если вы найдете, строку, которая соответствует критериям шаблонаb.
awk '/patterna/ || /patternb/ { print > "patternapatternb.txt" }' inputfile
входной файл
шаблон это
patternb, который
patterna that
паттерн, который
другой шаблон
patterna anotherthis
patternb anotherthat
выводит patternapatternb.txt:
паттерн это
patternb, что
patterna anotherthis
patternb другое, что
, и как это может быть достигнуто для многих пар шаблонов, чтобы иметь возможность записывать выходные данные каждой пары в другой файл
awk
обрабатывает каждую запись (по умолчанию запись - это строка) отдельно - для применения условий, охватывающих соседние строки, можно использовать функцию getline
для чтения следующей записи и проверки ее на соответствие второму шаблону:
awk '/patterna/ {
a=$0
if (getline > 0 && $0 ~ /patternb/) {
print a
print
}
}' inputfile
В качестве альтернативы можно использовать sed
sed -n '/patterna/ {$!N; /\npatternb/p}' inputfile
Если вы хотите выводить первое совпадение /patternb/
после каждого совпадения /patterna/
, предшествующее его /patterna/
, то вы можете сделать stateful синтаксический анализатор, устанавливая флаг при каждом совпадении /patterna/
и снимая его при каждом /patternb/
:
awk '
/patterna/ {
a=1; lasta=$0; next;
}
/patternb/ && a==1 {
a=0; print lasta; print;
}' inputfile
Чистое решение с использованием TXR , без явных манипуляций с состоянием или побочных эффектов, кроме вывода:
@(repeat)
patterna @this
@ (repeat)
patterna @other
@ (fail)
@ (last :mandatory)
patternb @that
@ (end)
@ (output)
patterna @this
patternb @that
@ (end)
@(end)
Выполнение:
$ txr pairs.txr data
patterna this
patternb that
patterna anotherthis
patternb anotherthat
В этом решении мы пытаемся зафиксируйте это требование: ключевое слово patternb
должно быть найдено после строки с patterna
. Это не обязательно должна быть следующая строка. Однако patternb
должен появиться до того, как появится другая строка, которая имеет patterna
: между данной строкой patterna
и соответствующей парной строкой patternb
существует не может быть другой строкой паттерна
.
Внутренняя итерация:
@ (repeat)
patterna @other
@ (fail)
@ (last :mandatory)
patternb @that
@ (end)
сканирует входные данные в поисках двух вещей: совпадения на
patterna @other
или обязательного завершающего совпадения
patternb @that
Однако, если найден шаблонa @other
, следующая за ним директива - @ (fail)
, которая приводит к сбою повтора. (При повторении устанавливается неявный @ (блок)
, а @ (сбой)
приводит к завершению самого внутреннего ограничивающего блока как неудачное сопоставление.)
Хорошо, основываясь на вашем более подробном объяснении, вы можете использовать pcregrep
pcregrep -M 'patterna(.*\n)patternb' inputfile > patternapatternb.txt
Этот одиночный лайнер даст вам
cat patternapatternb.txt
patterna this
patternb that
patterna another this
patternb another that
предыдущий ответ
Я использовал этот одиночный лайнер ...
awk '/patterna/ && /patternb/ {print > "patternapatterb.txt" } ' inputfile
И этот входной файл
cat inputfile
patterna patternb this
patterna patterna that
Результаты
cat patternapatterb.txt
patterna patternb this
Похоже, это именно то, что вы просили (вы сказали «но только когда оба верны»); однако, если мы неправильно поняли ваш запрос, сообщите нам об этом.
Если вы хотите сопоставить либо шаблон, либо шаблонb, вы можете использовать egrep
egrep "patterna||patternb" inputfile > patternapatternb.txt