Bash – awk starting from a fixed text, until the first blank line

awkbashsedshell-script

I'm trying to pipe into something that will return only the first "paragraph" or "section" separated by a blank line. I thought I could use awk or sed to get a range as per some other answers but it doesn't seem to work.

$ 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

Should it not return only the first "section"? (as per:
Grep starting from a fixed text, until the first blank line
and
https://www.unix.com/shell-programming-and-scripting/148692-awk-script-match-pattern-till-blank-line.html)

  • If I use grep -ve ^$ the blank lines get removed, so there's no special characters.
  • If I try to extract a different part, I get the parts from both "sections":

    $ 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
    
  • If I use sed -n '/^Package:/,/^$/p' or sed -n '/^Package:/,/^Version:/p' I get the same results as the equivalent awk.

How do I get awk or sed to stop after the first occurrence?

Best Answer

This is exactly why awk has a paragraph mode:

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

and to print the 2nd record is just the obvious change of NR==1 to NR==2:

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

Never use range expressions btw - they make code for trivial problems very slightly briefer than using a flag but then if your requirements change in the slightest require a complete rewrite or duplicate conditions. So any time you thing you might want to use /begin/,/end/ with sed or awk use /begin/{f=1} f{print} /end/{f=0} with awk instead and that gives you FAR more control on when/how to print the begin/end lines, etc.