awk извлекает строки, которые соответствуют обоим шаблонам, истинны

как я могу изменить приведенный ниже код, чтобы напечатать строки, которые соответствуют следующим критериям, но только если оба условия верны?

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

awk '/patterna/ || /patternb/ { print > "patternapatternb.txt" }' inputfile

входной файл
шаблон это
patternb, который
patterna that
паттерн, который
другой шаблон
patterna anotherthis
patternb anotherthat

выводит patternapatternb.txt:
паттерн это
patternb, что
patterna anotherthis
patternb другое, что

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

-1
22.09.2016, 19:41
3 ответа

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
1
28.01.2020, 05:08

Чистое решение с использованием 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) , которая приводит к сбою повтора. (При повторении устанавливается неявный @ (блок) , а @ (сбой) приводит к завершению самого внутреннего ограничивающего блока как неудачное сопоставление.)

1
28.01.2020, 05:08

Хорошо, основываясь на вашем более подробном объяснении, вы можете использовать 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
0
28.01.2020, 05:08

Теги

Похожие вопросы