Как grep, чтобы найти пропущенную строку - PullRequest
0 голосов
/ 01 февраля 2019

У меня есть файл с зарегистрированными HTTP-запросами следующим образом

POST pathX 
header1: any
header2: any
header3: CONSTANT

POST pathX 
header1: any
header2: any

POST pathX 
header1: any
header2: any
header3: CONSTANT
...

Я хотел бы найти все запросы, которые находятся по пути "pathX" и не содержат заголовок 3.
Числострок с заголовками может быть разным для каждого запроса, но обычно это 3 или 4.

Я могу найти все запросы к pathX и отобразить следующие 4 строки, такие как

cat file | grep "pathX" -A 4

.все 3 запроса, но на самом деле я ищу только второй, в котором нет строки "header3: CONSTANT".

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

С помощью awk:

awk -v RS=  '/pathX/ && !/header3/' file

Используя ваш входной файл, вы получите:

$ awk -v RS=  '/pathX/ && !/header3/' file
POST pathX 
header1: any
header2: any

Как это работает

  • -v RS=

    Это говорит awk использовать пустые строки в качестве разделителя записей.Это означает, что каждый запрос (POST и заголовки) считывается как одна запись.

  • /pathX/ && !/header3/

    Это говорит awk о печати любой записи, содержащей pathX но не header3.

0 голосов
/ 01 февраля 2019

Это сложно, используя обычные регулярные выражения grep.Однако если у вас есть доступ к программе, поддерживающей Perl-совместимые регулярные выражения (PCRE), например pcregrep, вы можете сделать следующее:

pcregrep <file -M '(?s)^POST pathX(?:(?!^header3:).)*?(\n\n|\Z)'
  • -M включает многострочное сопоставление
  • (?s) делает . совпадение \n, поэтому нам не нужно писать (\n|.)
  • (?!^header3:). соответствует любому символу, которому не предшествует header3: в начале строки
  • (?: ... )*? соответствует ... ноль или более раз, но как можно меньше, чтобы совпадение было успешным
  • (\n\n|\Z) соответствует пустой строке или концу файла
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...