Как напечатать линии между шаблоном и линией, начинающейся с другого шаблона? - PullRequest
0 голосов
/ 23 мая 2019

Мне нужна ваша помощь в разборе файла журнала с помощью AWK (желательно), чтобы извлечь только необходимую информацию. Я упростила это, чтобы быть более заметной, и это выглядит так:

2019-05-22 HH:MM:SS name:Jhon 1 + random_text
LOG_TEXT 1
LOG_TEXT 1
2019-05-22 HH:MM:SS whatever:Jhon 1 + random_text
2019-05-22 HH:MM:SS name:Jhon 2 + random_text
LOG_TEXT 2
LOG_TEXT 2
2019-05-22 HH:MM:SS ANYTHING 2 + random_text
2019-05-22 HH:MM:SS name:Jhon 3 + random_text
LOG_TEXT 3
LOG_TEXT 3
2019-05-22 HH:MM:SS name:Jhon 3 + random_text

Подробное описание:

Общая идея состоит в том, чтобы фильтровать только строки, содержащие «name: Jhon» (без учета: Jhon) и соответствующий им LOG TEXT (который может содержать что угодно, но не имеет метки времени!).

Я пронумеровал каждую строку в конце, чтобы сделать 3 группы возможных ситуаций более заметными (LOG TEXT, заканчивающийся строкой «what: JHON» (1-я строка не печатается); общей строкой с датой и меткой «ANYTHING» ( 2 - строка не напечатана) или с именем "JHON" (3 - строка напечатана))


Функциональность является частью рабочего процесса в Vmware Vrealize orchestrator (так что настоящий язык - JS, но я могу использовать ssh и awk), но я не буду углубляться в это.

Я пробовал различные шаблоны awk и regex, но не смог понять это. Самое близкое, что я мог получить, - это что-то похожее на это:

awk '/Jhon/{flag=1}/whatever/{flag=0}flag' file.txt

Но это неправильно, поскольку я считаю «что угодно» фиксированным шаблоном, а также, в этом случае строка, содержащая «НИЧЕГО», не фильтруется. В действительности, «что угодно» и «что угодно» (а также random_text и time HH: MM: SS) могут быть литературными и любыми. Поэтому единственный способ остановить сопоставление - это остановить его на строках, начинающихся с формата даты (но я не могу использовать 2019, так как он используется в каждой строке, отличной от LOG_TEXT).


Также пробовал с некоторым регулярным выражением JS, но это слишком сложно.

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

2019-05-22 HH:MM:SS name:Jhon 1 + random_text
LOG_TEXT 1
LOG_TEXT 1
2019-05-22 HH:MM:SS name:Jhon 2 + random_text
LOG_TEXT 2
LOG_TEXT 2
2019-05-22 HH:MM:SS name:Jhon 3 + random_text
LOG_TEXT 3
LOG_TEXT 3
2019-05-22 HH:MM:SS name:Jhon 3 + random_text

1 Ответ

1 голос
/ 23 мая 2019

Я бы попробовал что-то вроде этого:

 awk '$1 ~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/{if($0~/name:Jhon/){flag=1}else{flag=0}}flag' file.txt

Пояснения:

  • a ~ / pattern / проверит, соответствует ли переменная a pattern
  • В своем коде вы использовали /Jhon/{flag=1}. Это выражение является просто ярлыком для $0 ~ /Jhon/{flag=1}. Блок {flag=1} будет выполнен, если строка ($ 0) соответствует шаблону /John/
  • $1 ~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/ означает, что блок будет выполнен, если первый столбец строки соответствует формату даты YYYY-mm-dd (<4 цифры> - <2 цифры> - <2 цифры>)

    awk '
        # If first column matches a date format
        $1 ~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/{
            # If the line contains name:Jhon
            if($0~/name:Jhon/)
            {
                flag=1
            }
            else
            {
                flag=0
            }
        }
        # Prints if flag != 0
        flag
    ' file.txt
    

Но, конечно, если LOG_TEXT начинается где-то с даты, он потерпит неудачу.

Если LOG_TEXT всегда в 2 строках, вы можете попробовать это:

awk '{counter-=1}/name:Jhon/{counter=3}counter>0' file.txt

Возвращает

2019-05-22 HH:MM:SS name:Jhon 1 + random_text
LOG_TEXT 1
LOG_TEXT 1
2019-05-22 HH:MM:SS name:Jhon 2 + random_text
LOG_TEXT 2
LOG_TEXT 2
2019-05-22 HH:MM:SS name:Jhon 3 + random_text
LOG_TEXT 3
LOG_TEXT 3
2019-05-22 HH:MM:SS name:Jhon 3 + random_text
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...