awk ausgehend von einem festen Text, bis zur ersten Leerzeile

awk ausgehend von einem festen Text, bis zur ersten Leerzeile

Ich versuche, in etwas zu leiten, das nur den ersten „Absatz“ oder „Abschnitt“ zurückgibt, getrennt durch eine Leerzeile. Ich dachte, ich könnte awkoder verwenden sed, um einen Bereich wie in einigen anderen Antworten zu erhalten, aber es scheint nicht zu funktionieren.

$ cat txt
Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.9.1-0ubuntu0.1
Supported: 3y

Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.4-0ubuntu1
Supported: 3y

$ cat txt |awk '/^Package:/,/^$/'
Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.9.1-0ubuntu0.1
Supported: 3y

Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.4-0ubuntu1
Supported: 3y

Sollte nicht nur der erste „Abschnitt“ zurückgegeben werden? (gemäß: Grep ausgehend von einem festen Text, bis zur ersten leeren Zeile Und https://www.unix.com/shell-programming-and-scripting/148692-awk-script-match-pattern-till-blank-line.html)

  • Wenn ich es verwende, grep -ve ^$werden die Leerzeilen entfernt, so dass keine Sonderzeichen vorhanden sind.
  • Wenn ich versuche, einen anderen Teil zu extrahieren, erhalte ich die Teile aus beiden „Abschnitten“:

    $ cat txt |awk '/^Package:/,/^Version:/'
    Package: plasma-desktop
    Architecture: amd64
    Version: 4:5.12.9.1-0ubuntu0.1
    Package: plasma-desktop
    Architecture: amd64
    Version: 4:5.12.4-0ubuntu1
    
  • Wenn ich sed -n '/^Package:/,/^$/p'oder verwende sed -n '/^Package:/,/^Version:/p', erhalte ich die gleichen Ergebnisse wie mit dem entsprechenden awk.

Wie kann ich das Problem beheben awkbzw. sednach dem ersten Auftreten stoppen?

Antwort1

Genau aus diesem Grund verfügt awk über einen Absatzmodus:

$ awk -v RS= 'NR==1' file
Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.9.1-0ubuntu0.1
Supported: 3y

und das Drucken des zweiten Datensatzes ist nur die offensichtliche Änderung von NR==1in NR==2:

$ awk -v RS= 'NR==2' file
Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.4-0ubuntu1
Supported: 3y

Verwenden Sie übrigens niemals Bereichsausdrücke – sie machen den Code für triviale Probleme etwas kürzer als die Verwendung einer Flagge, aber wenn sich Ihre Anforderungen auch nur im Geringsten ändern, müssen Sie ihn komplett neu schreiben oder die Bedingungen duplizieren. Wenn Sie also denken, dass Sie /begin/,/end/sed oder awk verwenden möchten, verwenden Sie /begin/{f=1} f{print} /end/{f=0}stattdessen awk, und das gibt Ihnen VIEL mehr Kontrolle darüber, wann/wie die Anfangs-/Endzeilen usw. gedruckt werden.

Antwort2

In /begin/,/end/werden die „Aktionsflags“ bei jedem /begin/gefundenen Treffer aktiviert und bei gefundenem Treffer deaktiviert /end/. Die Begrenzungslinien mit „Beginn“ und „Ende“ werden ebenfalls gedruckt.

Ihre Eingaben haben folgende Auswirkungen (in den folgenden Beispielen ist hinter den gedruckten Zeilen ein Kommentar angebracht):

  • Mit '/^Package:/,/^$/':
    Package: plasma-desktop        #TURN ON
    Architecture: amd64            #
    Version: 4:5.12.9.1-0ubuntu0.1 #
    Supported: 3y                  #
                                   #TURN OFF
    Package: plasma-desktop        #TURN ON
    Architecture: amd64            #
    Version: 4:5.12.4-0ubuntu1     #
    Supported: 3y                  #
  • Mit '/^Package:/,/^Version:/':
    Package: plasma-desktop        #TURN ON
    Architecture: amd64            #
    Version: 4:5.12.9.1-0ubuntu0.1 #TURN OFF
    Supported: 3y

    Package: plasma-desktop        #TURN ON
    Architecture: amd64            #
    Version: 4:5.12.4-0ubuntu1     #TURN OFF
    Supported: 3y

Um nur den Absatz ab "Paket:" zu drucken, können Sie schreiben

sed -ne '/^$/q' -e '/^Package:/,$p' file

sedbricht die Verarbeitung der Datei ab, sobald es eine leere Zeile findet, weil /^$/q.

Mit awk:

awk '/^$/{exit};/^Package:/,0' file

Antwort3

Kommentar vonQuasimodo

/begin/,/end/ruft Zeilen ab, die diesen regulären Ausdrücken entsprechen, einschließlich der Begrenzungslinien. begin schaltet den Druck ein und end schaltet ihn aus. Die Zeile direkt nach Ihrer Leerzeile schaltet den Druck wieder ein, weil sie auch enthält Package:.

Mir ist aufgefallen, dass ich „to“ verwenden sedund ändern kann und es dann am Anfang beginnt. Da es nur einen Anfang gibt, wird es nur einmal übereinstimmen./begin/0

$ cat txt |sed -n '0,/^$/p'
Package: plasma-desktop
Architecture: amd64
Version: 4:5.12.9.1-0ubuntu0.1
Supported: 3y

verwandte Informationen