Извлечение многострочного вывода, если в скобках содержится определенное слово И - PullRequest
1 голос
/ 29 июня 2019

У меня есть такой ввод:

Jun 29 16:46:13 iPhone SomeThing[79987] <Notice>: [AppName] file.x:115 DEBUG: ClassNumberOne viewControllers: (
    "<UINavigationController: 0x105031a00>",
    "<UINavigationController: 0x10505ba00>",
    "<UINavigationController: 0x10486fe00>",
    "<UINavigationController: 0x105052600>",
    "<UINavigationController: 0x105065c00>"
)
Jun 29 16:46:13 iPhone SomeThing[79987] <Notice>: [AppName] file.x:151 DEBUG: ClassNumberTwo ARG2 2

Здесь нужно сопоставить два случая, один из которых состоит из нескольких строк, а другой - из одной строки. Критерий таков: у него должно быть ключевое слово DEBUG:. Для многострочного, если эта строка имеет ключевое слово и и (, то она должна совпадать до конца ). Каждая строка отделяется разделителем новой строки. Я не могу понять это. В настоящее время я использую простой grep DEBUG: и все. Но для многострочного сценария все потеряно, кроме первого. И я не знаком с perl, есть идеи? Заранее спасибо!

Обратите внимание, что я на iOS (взломан), поэтому другой инструмент может быть ограничен.

EDIT:

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

Ответы [ 2 ]

2 голосов
/ 29 июня 2019

С любым awk в любой оболочке на каждой коробке UNIX:

$ awk 'f; /\)/{f=0} /DEBUG:/{print; f=/\(/}' file
Jun 29 16:46:13 iPhone SomeThing[79987] <Notice>: [AppName] file.x:115 DEBUG: ClassNumberOne viewControllers: (
    "<UINavigationController: 0x105031a00>",
    "<UINavigationController: 0x10505ba00>",
    "<UINavigationController: 0x10486fe00>",
    "<UINavigationController: 0x105052600>",
    "<UINavigationController: 0x105065c00>"
)
Jun 29 16:46:13 iPhone SomeThing[79987] <Notice>: [AppName] file.x:151 DEBUG: ClassNumberTwo ARG2 2

Пояснение:

awk '       # WHILE read line DO 
f;          #    IF the flag `f` is set THEN print the current line ENDIF
/\)/{f=0}   #    IF the current line contains `)` THEN clear the flag ENDIF
/DEBUG:/ {  #    IF the current line contains `DEBUG:` THEN
    print;  #        print the line
    f=/\(/  #        set the flag `f` to 1 if the line contains `(`, 0 otherwise
}           #    ENDIF
' file      # ENDWHILE
1 голос
/ 29 июня 2019

Вот пример использования регулярных выражений в Perl (но это, вероятно, должно обрабатываться более точно с помощью синтаксического анализатора, например Regexp::Grammars):

use feature qw(say);
use strict;
use warnings;

my $data = do { local $/; <> };
my @lines = $data 
  =~ /
         ^( (?:(?!$).)* DEBUG:
             (?: 
                 (?: [^(]*? $ ) 
              | 
                 (?: (?:(?!$).)* \( [^)]* \) .*? $ )
             )
         )/gmsx;

say for @lines;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...