В sed или awk, как мне обрабатывать разделители записей, которые * могут * занимать несколько строк?

StackOverflow https://stackoverflow.com/questions/310191

  •  10-07-2019
  •  | 
  •  

Вопрос

Мой файл журнала - это:

 Wed Nov 12 blah blah blah blah cat1
 Wed Nov 12 blah blah blah blah
 Wed Nov 12 blah blah blah blah 
 Wed Nov 12 blah blah blah blah cat2
     more blah blah
     even more blah blah
 Wed Nov 12 blah blah blah blah cat3
 Wed Nov 12 blah blah blah blah cat4

Я хочу разобрать полные многострочные записи, где cat находится в первой строке.Каков наилучший способ сделать это в sed и/или awk?

т. е.я хочу, чтобы мой синтаксический анализ производил:

 Wed Nov 12 blah blah blah blah cat1
 Wed Nov 12 blah blah blah blah cat2
     more blah blah
     even more blah blah
 Wed Nov 12 blah blah blah blah cat3
 Wed Nov 12 blah blah blah blah cat4
Это было полезно?

Решение

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

awk " BEGIN { multiline = 0;} 
      ! /^ / { if (whatever) 
                 { print; multiline = 1;} 
               else 
                 multiline = 0; 
             } 
        /^ / {if (multiline == 1) 
                 print;
             } 
     " 
      yourfile

где whatever это ваша проверка, должен ли произойти ваш вывод (напримердля кошки).

Другие советы

Предполагая, что ваш файл журнала не содержит управляющих символов '\01' и '\02', и чтобы непрерывная строка начиналась ровно с четырех пробелов, могло бы сработать следующее:

c1=`echo -en '\01'`
c2=`echo -en '\02'`
cat logfile | tr '\n' $c1 | sed "s/$c1    /$c2/g" | sed "s/$c1/\n/g" | grep cat | sed "s/$c2/\n    /g"

Объяснение:это заменяет каждую новую строку на ASCII 1 (управляющий символ, который никогда не должен появляться в файле журнала), а каждую последовательность "новая строка-пробел-пробел-пробел-пробел" на ASCII 2 (другой управляющий символ).Затем он повторно заменяет ASCII 1 на новые строки, так что теперь каждая последовательность из нескольких строк помещается в одну строку, а старые разрывы строк заменяются ASCII 2.Это используется для cat, а затем ASCII 2 повторно заменяются комбинацией новая строка-пробел-пробел-пробел-пробел.

Что-то вроде этого?

awk 'function print_part() { if(cat) print part }  /^  / { part = part "\n" $0; next } /cat[0-9]$/ { print_part(); part = $0; cat = 1; next;  } { print_part(); cat=0} END { print_part() }' inputfile

В /^ / регулярное выражение определяет строки продолжения.

В /cat[0-9]$/ регулярное выражение определяет начальные строки, которые вы хотите сохранить.

Другой подход состоял бы в том, чтобы установить RS быть чем-то отличным от обычного \n.Например:

$ awk -v Pre=Wed 'BEGIN {RS = "\\n?\\s*" Pre} /cat.\n?/ {print Pre $0}' file.log
Wed Nov 12 blah blah blah blah cat1
Wed Nov 12 blah blah blah blah cat2
     more blah blah
     even more blah blah
Wed Nov 12 blah blah blah blah cat3
Wed Nov 12 blah blah blah blah cat4
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top