Em sed ou awk, como faço para lidar com separadores de registro que * pode * abranger várias linhas?
Pergunta
Meu arquivo de log é:
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
Eu quero analisar as entradas de várias linhas completas onde o gato é encontrado na primeira linha. Qual é a melhor maneira de fazer isso em sed
e / ou awk
?
i. eu quero minha análise a produtos:
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
Solução
Se você dizer que cada linha que começa com o espaço é uma continuação da folling sua fácil com (g) awk (este é da minha memória, talvez por isso, contém alguns erros menores, e para melhor legibilidade com algumas quebras de linha adicionais):
awk " BEGIN { multiline = 0;}
! /^ / { if (whatever)
{ print; multiline = 1;}
else
multiline = 0;
}
/^ / {if (multiline == 1)
print;
}
"
yourfile
onde whatever
é seu cheque se a sua saída deve acontecer (por exemplo, para o gato).
Outras dicas
Assumindo que o seu arquivo de log não contém o '\01'
caracteres de controle e '\02'
, e que uma linha contínua começa com exatamente quatro espaços, o seguinte trabalho podem:
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"
Explicação: este substitui cada nova linha com ASCII 1 (um caractere de controle que nunca deveria aparecer em um arquivo de log) e cada seqüência de "nova linha-espaço-espaço-espaço-space" com ASCII 2 (outro caractere de controle). Em seguida, re-substitui ASCII 1 com novas linhas, então agora cada seqüência de várias linhas é colocado em uma linha, com os antigos quebras de linha substituídos por ASCII 2. Isto é grepped para o gato, e, em seguida, o ASCII 2 de são re-substituído pelo combinação nova linha-espaço-espaço-espaço-espaço.
Algo como isso?
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
Os /^ /
linhas identifica expressões regulares de continuação.
Os identifica /cat[0-9]$/
regexp as linhas iniciais que você deseja manter.
Outra abordagem seria a criação RS
ser algo diferente do \n
normal. Por exemplo:
$ 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