In sed o awk, come gestisco i separatori di record che * possono * estendersi su più righe?

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

  •  10-07-2019
  •  | 
  •  

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
È stato utile?

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top