Verwenden Sie awk, um eine Zeile nach der N-Ausgabe einzufügen


7

Ich habe eine Textdatei mit einer Reihe von Daten gefüllt. Ich muss Zeilen herausziehen, die bestimmte Zeichenfolgen enthalten. Ich habe dies mit awk wie folgt erreicht:

awk '/pattern1|pattern2|pattern3/ {print;}' infile

Ich muss dann nach jeder dritten Zeile eine neue Zeile (\ n) einfügen. Also müsste es so aussehen

pattern1
pattern2
pattern3
<new line>
pattern1...

Ich konnte dies erreichen, indem ich den ersten Befehl in eine andere awk-Anweisung leitete

awk -F '\n' '/pattern1|pattern2|pattern3/ { print; }' infile | awk '{ if ((NR % 3) == 1) printf("\n"); print; }'

Ich denke, dass es einen effizienteren Weg geben muss, also begann ich zu suchen, wie ich die beiden Befehle miteinander kombinieren könnte. Ich habe folgendes versucht:

awk '/pattern1|pattern2|pattern3/ { if ((NR % 3) ==1 ) printf("\n"); print; }'

Ich dachte, das würde funktionieren, aber die Ausgabe ist völlig unvorhersehbar. Manchmal sind 5 Zeilen gruppiert, Gruppen von 2 Zeilen, aber keine Zeilen von 3.

Ich dachte, dass es vielleicht ein Trennzeichenproblem gibt, also habe ich versucht, mit der Option -F zu spielen und das IFS einzustellen, aber weder die Ausgabe geändert.

Ich glaube, ich mache etwas Dummes in der Art, wie ich versucht habe, die Musterübereinstimmung mit der if-Anweisung zu kombinieren, aber ich konnte die Kombination nicht herausfinden.

Ist das, was ich versuche, in einem einzigen awk-Befehl möglich? Und wenn ja, wo mache ich etwas falsch?

Antworten:


7

Das Problem bei Ihrem Lösungsversuch besteht darin, dass awk's NReine Anzahl der Eingabedatensätze ist , während Sie die neue Zeile basierend auf der Anzahl der Ausgabedatensätze einfügen möchten .

Ich glaube nicht, dass awk eine solche Zählung von Haus aus durchführt, aber Sie könnten so etwas tun

awk '/pattern1|pattern2|pattern3/ {print; if (++onr%3 == 0) print ""; }' infile

In diesem Fall definieren wir eine neue Variable onr(für die Ausgabenummer des Datensatzes - der Variablenname ist beliebig) und erhöhen sie jedes Mal, wenn wir den gewünschten Text abgleichen / drucken. Überprüfen Sie dann, ob dieser durch 3 teilbar ist, und drucken Sie in diesem Fall eine neue Zeile.


Hey @steeldriver. Was Sie sagen, macht absolut Sinn. Ich habe gelesen, dass NR für Eingabedatensätze ist. Aber ich habe keine Verbindung hergestellt, wie ich die Logik angewendet habe. Ich habe offensichtlich kein vollständiges Verständnis. Ihre Lösung funktioniert! Es gibt jetzt eine seltsame Sache; Aus irgendeinem Grund gibt es jetzt 2 Leerzeilen zwischen jeder Gruppe von 3. Ich werde sehen, ob ich herausfinden kann, warum. Entschuldigung für meine Unwissenheit, aber was macht das "++ onr%" genau? Ich denke, es zählt, aber ich erkenne das onr nicht. Vielen Dank!
Bourne

Hmmm, ich habe den zweiten Druck in "" geändert und es wurde die zusätzliche leere Zeile angezeigt. Ich glaube ich weiß warum jetzt. Dies liegt daran, dass sich in der Datei ein Datenblock befindet, gefolgt von einer Leerzeile und einem weiteren Datenblock. Und mit Ihrer viel saubereren awk-Aussage wird diese ursprüngliche leere Zeile nicht entfernt.
Bourne

Hoppla, Sie haben Recht - die zusätzliche neue Zeile ist ein Fehler in meinem Code ( printfügt standardmäßig eine neue Zeile hinzu). Wie Sie bereits bemerkt haben, kann dies durch Ändern in behoben werden print ""- oder Sie können es verwenden printf "\n". Ich werde die Antwort bearbeiten.
Steeldriver

Vielen Dank! Ich schätze deine Hilfe sehr. Ich habe noch viel zu lernen.
Bourne

0

Verstehe ich richtig, du versuchst zu erfinden

awk '/pattern1|pattern2/ {print $1;} /pattern3/ {print $1 "\n"}' infile

Hi @ vasily-vm. Ich glaube nicht, dass ich versuchen zu erfinden. In erster Linie versuche ich meinen awk Code zu verbessern. Ich brauche die 3 Muster, um sie zu gruppieren. Die Sache ist, dass ich am Ende mehrere 3er-Gruppen haben werde. Nach jeder 3er-Gruppe muss ich aufgrund einiger Formatierungsbeschränkungen eine Leerzeile einfügen. Cheers
Bourne

Entschuldigung, schlechte Formulierung :( Tatsächlich schlage ich vor, Muster in zwei Gruppen aufzuteilen: Die erste kopiert sie einfach, die zweite - druckt eine zusätzliche neue Zeile, nachdem das in meiner Antwort
angegebene
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.