Извлечение определенных строк набора, соответствующих правилу

У меня большой файл с журналами, как показано ниже. В журнале зарегистрировано около 30000 экземпляров таких событий. Мне нужно извлечь эти строки, начинающиеся с RINGING и CLOSE (включая), и которые не содержат 30 30 .

Требование:

Из двух примеров, представленных ниже, мне нужен только экземпляр 2. Экземпляра 1 необходимо полностью удалить (они образуют большую часть файла)

Экземпляр 1:

 313782 Aug 19 18:37:04.925: <DATA> RINGING|254|01136097645|5950|$hostIp|$size |$data 313783 Aug 19 18:37:05.262: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data 313784 Aug 19 18:37:09.028: <DATA> OUT |254|01136097645|5950|$hostIp|2 bytes |30 93 313785 Aug 19 18:37:09.705: <DATA> IN |254|01136097645|5950|$hostIp|4 bytes |30 73 F9 F8 313786 Aug 19 18:37:18.532: <DATA> IN |254|01136097645|5950|$hostIp|336 bytes |30 10 60 00 06 00 00 6F 12 00 ... 313787 Aug 19 18:37:19.485: <DATA> OUT |254|01136097645|5950|$hostIp|133 bytes |30 30 60 00 00 00 06 6F 12 10 ... 313788 Aug 19 18:37:20.898: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data 313789 Aug 19 18:37:22.006: <DATA> CLOSE|254|01136097645|5950|$hostIp|$size |$data 

Экземпляр 2:

(Линия с 30 30 нет)

 313782 Aug 19 18:37:04.925: <DATA> RINGING|254|01136097645|5950|$hostIp|$size |$data 313783 Aug 19 18:37:05.262: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data 313784 Aug 19 18:37:09.028: <DATA> OUT |254|01136097645|5950|$hostIp|2 bytes |30 93 313785 Aug 19 18:37:09.705: <DATA> IN |254|01136097645|5950|$hostIp|4 bytes |30 73 F9 F8 313786 Aug 19 18:37:18.532: <DATA> IN |254|01136097645|5950|$hostIp|336 bytes |30 10 60 00 06 00 00 6F 12 00 ... 313788 Aug 19 18:37:20.898: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data 313789 Aug 19 18:37:22.006: <DATA> CLOSE|254|01136097645|5950|$hostIp|$size |$data 

  • Удалить все до «/» на каждой строке
  • bash regex для поиска и сохранения строки из файла
  • исключить строки из файла на основе определенных значений в определенных столбцах
  • Как присоединиться к строкам vCards
  • Извлечение подмножества строк файла на основе регулярного выражения для первой и последней строки
  • Удаление повторяющихся слов между скобками inline
  • Перемещайте каждую строку до конца строки, содержащей символ
  • Как заменить текст в столбце
  • 2 Solutions collect form web for “Извлечение определенных строк набора, соответствующих правилу”

    Предполагая, что ваш файл журнала называется logfile , вот решение awk с образцом вывода:

     $ awk '/RINGING/,/CLOSE/ {if (/30 30/){f=1}; a=a"\n"$0} f==0 && /CLOSE/ {print a} /CLOSE/{a="";f=0}' logfile 313782 Aug 19 18:37:04.925: <DATA> RINGING|254|01136097645|5950|$hostIp|$size |$data 313783 Aug 19 18:37:05.262: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data 313784 Aug 19 18:37:09.028: <DATA> OUT |254|01136097645|5950|$hostIp|2 bytes |30 93 313785 Aug 19 18:37:09.705: <DATA> IN |254|01136097645|5950|$hostIp|4 bytes |30 73 F9 F8 313786 Aug 19 18:37:18.532: <DATA> IN |254|01136097645|5950|$hostIp|336 bytes |30 10 60 00 06 00 00 6F 12 00 313788 Aug 19 18:37:20.898: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data 313789 Aug 19 18:37:22.006: <DATA> CLOSE|254|01136097645|5950|$hostIp|$size |$data 

    объяснение

    Принимая каждую команду awk по очереди:

    • /RINGING/,/CLOSE/ {if (/30 30/){f=1}; a=a"\n"$0}

      Выражение /RINGING/,/CLOSE/ – это диапазон: он указывает, что эта команда применяется только к группам строк. Группа начинается, когда встречается строка, включающая текст RINGING . Группа заканчивается, когда встречается строка, включающая текст CLOSE . Для любой строки в такой группе выполняются команды в фигурных скобках. Первый из них устанавливает флаг f в один, если строка содержит 30 30 . Вторая команда добавляет текущую строку к переменной a .

    • f==0 && /CLOSE/ {print a}

      Командам в фигурных скобках здесь предшествуют два условия и вместе. Первое условие указывает, что флаг f равен нулю (это означает, что 30 30 не было найдено в этой группе), а второе указывает, что эта строка содержит текст CLOSE . Если оба этих условия выполнены, то строка строк, хранящихся в переменной, печатается.

    • /CLOSE/{a="";f=0}

      Наконец, в любой строке, содержащей текст CLOSE , переменная a сбрасывается в пустую строку, а флаг f устанавливается в ноль. Когда это будет сделано, код будет готов к запуску в следующей группе строк, если он есть.

    Это может быть возможно с использованием perl-совместимого регулярного выражения (PCRE), например

     pcregrep -M '^.*?RINGING(?(?!30 30)(?s).)+?CLOSE.*?$' file 

    или

     grep -zPo '^.*?RINGING(?(?!30 30)(?s).)+?CLOSE.*?$' file 

    Альтернативно, использование более выразительного разделителя записей GNU awk

     gawk -vRS="CLOSE[^\n]*\n" -vORS= '!/30 30/ {print; print RT}' file 
    Linux и Unix - лучшая ОС в мире.