In sed o awk, come gestisco i separatori di record che * possono * estendersi su più righe?
Domanda
Il mio file di registro è:
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
Voglio analizzare tutte le voci multilinea in cui si trova cat sulla prima riga. Qual è il modo migliore per farlo in sed
e / o awk
?
vale a dire. voglio che la mia analisi produca:
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
Soluzione
se dici che ogni riga che inizia con lo spazio è una continuazione del folling è facile con (g) awk (questo è dalla mia memoria, quindi forse contiene alcuni errori di battitura minori, e per una migliore leggibilità con alcune interruzioni di riga aggiuntive):
awk " BEGIN { multiline = 0;}
! /^ / { if (whatever)
{ print; multiline = 1;}
else
multiline = 0;
}
/^ / {if (multiline == 1)
print;
}
"
yourfile
dove qualunque
è il tuo controllo se il tuo output dovrebbe avvenire (ad es. per il gatto).
Altri suggerimenti
Supponendo che il tuo file di registro non contenga i caratteri di controllo '\ 01'
e '\ 02'
e che una riga continua inizi esattamente con quattro spazi, i seguenti potrebbe funzionare:
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"
Spiegazione: sostituisce ogni nuova riga con ASCII 1 (un carattere di controllo che non dovrebbe mai apparire in un file di registro) e ogni sequenza "newline-space-space-space-space" con ASCII 2 (un altro carattere di controllo). Sostituisce quindi ASCII 1 con le nuove righe, quindi ora ogni sequenza di più righe viene inserita in una riga, con le vecchie interruzioni di riga sostituite da ASCII 2. Questo viene sostituito per cat, quindi gli ASCII 2 vengono sostituiti con combinazione newline-spazio-spazio-spazio-spazio.
Qualcosa del genere?
awk 'function print_part() { if(cat) print part } /^ / { part = part "\n" <*>; next } /cat[0-9]$/ { print_part(); part = <*>; cat = 1; next; } { print_part(); cat=0} END { print_part() }' inputfile
Il regexp / ^ /
identifica le linee di continuazione.
Il regexp / cat [0-9] $ /
identifica le linee di partenza che vuoi mantenere.
Un altro approccio sarebbe quello di impostare RS
come qualcosa di diverso dal normale \ n
. Ad esempio:
$ awk -v Pre=Wed 'BEGIN {RS = "\\n?\\s*" Pre} /cat.\n?/ {print Pre <*>}' 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