In sed oder awk, wie gehe ich mit Rekord Separatoren, die * kann * Spanne mehrere Zeilen?

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

  •  10-07-2019
  •  | 
  •  

Frage

Meine Protokolldatei ist:

 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

Ich mag die vollen mehrzeilige Einträge analysieren, wo Katze auf der ersten Zeile gefunden wird. Was ist der beste Weg, dies in sed zu tun und / oder awk?

d. ich möchte meine Parse produzieren:

 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
War es hilfreich?

Lösung

Wenn Sie sagen, jede Zeile, die mit Raum beginnt, ist eine Fortsetzung der Folling seine leicht mit (g) awk (dies aus meinem Gedächtnis ist, so vielleicht ist es ein paar kleinere Fehler enthält, und zur besseren Lesbarkeit mit einigen zusätzlichen Zeilenumbrüche):

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

wo whatever ist Ihre überprüfen, ob Ihr Ausgang (zum Beispiel für die Katze) geschehen soll.

Andere Tipps

Ihre Log-Datei Unter der Annahme, nicht die Steuerzeichen '\01' und '\02' enthalten, und dass eine fortgesetzte Linie mit genau vier Leerzeichen beginnt, kann die folgende Arbeit:

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"

Erläuterung: diese ersetzt jedes Newline mit ASCII 1 (ein Steuerzeichen, die nie in einer Log-Datei angezeigt werden sollen) und jede Sequenz „Newline-Raum-Raum-Raum-Raum“ mit ASCII 2 (einem anderen Steuerzeichen). Es dann wieder ersetzt ASCII 1 mit Zeilenumbrüchen, so dass nun jede Folge von mehreren Zeilen in eine Zeile setzen, mit den alten Zeilenumbrüchen durch ASCII ersetzt 2. Dieser für Katzen grep wird, und dann wird die ASCII 2 die wieder ersetzt mit der newline-Raum-Raum-Raum-Raum-Kombination.

So etwas wie das?

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

Die /^ / regexp identifiziert Fortsetzungszeilen.

Die /cat[0-9]$/ regexp identifiziert die Starterlinien Sie behalten möchten.

Ein weiterer Ansatz wäre RS zu setzen, etwas anderes als die normalen \n zu sein. Zum Beispiel:

$ 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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top