awk, начиная с фиксированного текста, до первой пустой строки

awk, начиная с фиксированного текста, до первой пустой строки

Я пытаюсь передать что-то, что вернет только первый "абзац" или "раздел", разделенный пустой строкой. Я думал, что могу использовать awkили, sedчтобы получить диапазон, как в некоторых других ответах, но это, похоже, не работает.

$ 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

Разве он не должен возвращать только первый «раздел»? (согласно: Grep, начиная с фиксированного текста, до первой пустой строки и https://www.unix.com/shell-programming-and-scripting/148692-awk-script-match-pattern-till-blank-line.html)

  • Если я использую grep -ve ^$его, пустые строки удаляются, поэтому нет никаких специальных символов.
  • Если я попытаюсь извлечь другую часть, я получу части из обоих «разделов»:

    $ 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
    
  • Если я использую sed -n '/^Package:/,/^$/p'или , sed -n '/^Package:/,/^Version:/p'я получаю те же результаты, что и эквивалент awk.

Как мне получить awkили sedпрекратить после первого случая?

решение1

Именно поэтому в awk есть режим абзаца:

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

и для печати 2-й записи достаточно просто очевидно изменить NR==1на NR==2:

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

Кстати, никогда не используйте выражения диапазонов - они делают код для тривиальных проблем немного короче, чем при использовании флага, но затем, если ваши требования изменятся хоть немного, потребуется полностью переписать или дублировать условия. Так что в любое время, когда вы думаете, что вам может понадобиться использовать /begin/,/end/sed или awk, используйте /begin/{f=1} f{print} /end/{f=0}вместо этого awk, и это даст вам НАМНОГО больше контроля над тем, когда/как печатать начальные/конечные строки и т. д.

решение2

В /begin/,/end/"флаги действий" включаются каждый раз, когда /begin/находится совпадение, и выключаются, когда /end/совпадение находится. Также печатаются линии границ с "begin" и "end".

Последствия вашего ввода таковы (в приведенных ниже примерах после напечатанных строк дается комментарий):

  • С '/^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                  #
  • С '/^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

Чтобы напечатать только абзац, начинающийся с «Пакет:», вы можете написать

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

sedпрекращает обработку файла, как только находит пустую строку из-за /^$/q.

С awk:

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

решение3

Как прокомментировалКвазимодо

/begin/,/end/получает строки, которые соответствуют этим регулярным выражениям, включая граничные строки. begin включает печать, а end выключает. Строка сразу после вашей пустой строки снова включает печать, потому что Package:в ней также есть.

Я понял, что могу использовать sedи изменить /begin/to 0, и он начнется с начала. Поскольку начало только одно, оно совпадет только один раз.

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

Связанный контент