Извлечение уникальной части текста из файла с помощью awk, sed или grep

Из вывода pactl list sink-inputs мне нужно захватить входной номер приемника для VLC. До этого я пытаюсь извлечь часть, содержащую вывод только для VLC. Все методы, которые, как я думал, будут работать, имеют недостатки. Это примерный результат:

 $ pactl list sink-inputs Sink Input #1373 Driver: protocol-native.c Owner Module: 9 Client: 10350 Sink: 0 Sample Specification: float32le 2ch 44100Hz Channel Map: front-left,front-right Format: pcm, format.sample_format = "\"float32le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\"" Corked: no Mute: no Volume: 0: 100% 1: 100% 0: 0,00 dB 1: 0,00 dB balance 0,00 Buffer Latency: 453287 usec Sink Latency: 19697 usec Resample method: copy Properties: media.role = "video" media.name = "audio stream" application.name = "VLC media player (LibVLC 2.1.5)" native-protocol.peer = "UNIX socket client" native-protocol.version = "28" application.id = "org.VideoLAN.VLC" application.version = "2.1.5" application.icon_name = "vlc" application.language = "pt_BR.UTF-8" application.process.id = "19965" application.process.machine_id = "948146522454ae6aa2bb8ed153f4bce4" application.process.session_id = "948146522454ae6aa2bb8ed153f4bce4-1431635199.85146-1790309877" application.process.user = "teresaejunior" application.process.host = "localhost" application.process.binary = "vlc" window.x11.display = ":0.0" module-stream-restore.id = "sink-input-by-media-role:video" Sink Input #1378 Driver: protocol-native.c Owner Module: 9 Client: 10378 Sink: 0 Sample Specification: s16le 2ch 44100Hz Channel Map: front-left,front-right Format: pcm, format.sample_format = "\"s16le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\"" Corked: no Mute: no Volume: 0: 87% 1: 87% 0: -3,63 dB 1: -3,63 dB balance 0,00 Buffer Latency: 989841 usec Sink Latency: 19572 usec Resample method: n/a Properties: media.name = "audio stream" application.name = "mplayer2" native-protocol.peer = "UNIX socket client" native-protocol.version = "28" application.process.id = "20093" application.process.user = "teresaejunior" application.process.host = "localhost" application.process.binary = "mplayer2" application.language = "C" window.x11.display = ":0.0" application.process.machine_id = "948146522454ae6aa2bb8ed153f4bce4" module-stream-restore.id = "sink-input-by-application-name:mplayer2" 

Оба awk '/^Sink/,/VLC/' и sed -n '/^Sink/,/VLC/p' захватывают часть VLC, но затем также захватывают часть mplayer2 и идут до конца вывода:

 $ pactl list sink-inputs | awk '/^Sink/,/VLC/' Sink Input #1373 Driver: protocol-native.c Owner Module: 9 Client: 10350 Sink: 0 Sample Specification: float32le 2ch 44100Hz Channel Map: front-left,front-right Format: pcm, format.sample_format = "\"float32le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\"" Corked: no Mute: no Volume: 0: 100% 1: 100% 0: 0,00 dB 1: 0,00 dB balance 0,00 Buffer Latency: 437414 usec Sink Latency: 19666 usec Resample method: copy Properties: media.role = "video" media.name = "audio stream" application.name = "VLC media player (LibVLC 2.1.5)" Sink Input #1379 Driver: protocol-native.c Owner Module: 9 Client: 10381 Sink: 0 Sample Specification: s16le 2ch 44100Hz Channel Map: front-left,front-right Format: pcm, format.sample_format = "\"s16le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\"" Corked: no Mute: no Volume: 0: 87% 1: 87% 0: -3,63 dB 1: -3,63 dB balance 0,00 Buffer Latency: 980045 usec Sink Latency: 19563 usec Resample method: n/a Properties: media.name = "audio stream" application.name = "mplayer2" native-protocol.peer = "UNIX socket client" native-protocol.version = "28" application.process.id = "20093" application.process.user = "teresaejunior" application.process.host = "localhost" application.process.binary = "mplayer2" application.language = "C" window.x11.display = ":0.0" application.process.machine_id = "948146522454ae6aa2bb8ed153f4bce4" module-stream-restore.id = "sink-input-by-application-name:mplayer2" 

grep -Poz '^Sink(?s).*?VLC' работает, но если выход VLC должен появиться после mplayer2, он потерпит неудачу (тест с mplayer2 вместо VLC):

 $ pactl list sink-inputs | grep -Poz '^Sink(?s).*?mplayer' Sink Input #1373 Driver: protocol-native.c Owner Module: 9 Client: 10350 Sink: 0 Sample Specification: float32le 2ch 44100Hz Channel Map: front-left,front-right Format: pcm, format.sample_format = "\"float32le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\"" Corked: no Mute: no Volume: 0: 100% 1: 100% 0: 0,00 dB 1: 0,00 dB balance 0,00 Buffer Latency: 441088 usec Sink Latency: 18159 usec Resample method: copy Properties: media.role = "video" media.name = "audio stream" application.name = "VLC media player (LibVLC 2.1.5)" native-protocol.peer = "UNIX socket client" native-protocol.version = "28" application.id = "org.VideoLAN.VLC" application.version = "2.1.5" application.icon_name = "vlc" application.language = "pt_BR.UTF-8" application.process.id = "19965" application.process.machine_id = "948146522454ae6aa2bb8ed153f4bce4" application.process.session_id = "948146522454ae6aa2bb8ed153f4bce4-1431635199.85146-1790309877" application.process.user = "teresaejunior" application.process.host = "localhost" application.process.binary = "vlc" window.x11.display = ":0.0" module-stream-restore.id = "sink-input-by-media-role:video" Sink Input #1380 Driver: protocol-native.c Owner Module: 9 Client: 10396 Sink: 0 Sample Specification: s16le 2ch 44100Hz Channel Map: front-left,front-right Format: pcm, format.sample_format = "\"s16le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\"" Corked: no Mute: no Volume: 0: 87% 1: 87% 0: -3,63 dB 1: -3,63 dB balance 0,00 Buffer Latency: 989841 usec Sink Latency: 18084 usec Resample method: n/a Properties: media.name = "audio stream" application.name = "mplayer 

Желаемый результат:

 Sink Input #1373 Driver: protocol-native.c Owner Module: 9 Client: 10350 Sink: 0 Sample Specification: float32le 2ch 44100Hz Channel Map: front-left,front-right Format: pcm, format.sample_format = "\"float32le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\"" Corked: no Mute: no Volume: 0: 100% 1: 100% 0: 0,00 dB 1: 0,00 dB balance 0,00 Buffer Latency: 441088 usec Sink Latency: 18159 usec Resample method: copy Properties: media.role = "video" media.name = "audio stream" application.name = "VLC media player (LibVLC 2.1.5)" 

  • В POSIX sed период (точка) соответствует новой строке в многострочном пространстве шаблонов?
  • Как найти текст, скопировать его и вставить в следующую строку в файле?
  • Сбросьте шаблон слова в конце строки, используя sed
  • Bash - Конвертировать символ escape-символа в BBCode
  • Обработка текста. Создание файла slurm topology.conf из вывода ibnetdiscover.
  • Есть ли надежный инструмент командной строки для обработки CSV-файлов?
  • Как использовать регулярное выражение с AWK для замены строки?
  • Поведение POSIX привязок sed и $ regex с многострочными пространствами шаблонов
  • 3 Solutions collect form web for “Извлечение уникальной части текста из файла с помощью awk, sed или grep”

    С ed :

     ed -s <<'IN' r !pactl list sink-inputs /VLC/+,$d ?Sink Input?,.p q IN 

    Он выводит вывод команды в текстовый буфер, d выделяет все после первой строки, соответствующей VLC а затем p rints от предыдущей строки, соответствующей Sink Input до текущей строки.

    С sed :

     pactl list sink-inputs | sed -n 'H;/Sink Input/h;/VLC/{x;p;q}' 

    Он добавляет каждую строку в H старый буфер, если строка соответствует Sink Input она перезаписывает h старый буфер, а когда строка соответствует VLC, e x изменяет пространство удержания w. пространство рисунка, p rints и q uits.

    Я бы использовал режим абзаца Perl:

     pactl list sink-inputs | perl -00ne 'print if s/(.*?VLC.*?\n).*/$1/ms' 

    Параметр -00 устанавливает разделитель входных данных в \n\n поэтому «строка» является абзацем. Затем подстановка будет соответствовать всем, пока первая VLC а затем ничего до первой новой строки, и сохранит их как $1 . Все после этого удаляется (поскольку мы заменяем все $1 ). Наконец, печатаются строки, в которых эта замена была успешной.

    Это эффективные многострочные записи, разделенные пустой строкой. Awk отлично подходит для обработки таких данных:

     pactl list sink-inputs | awk -v RS="" '/VLC/' 

    Если вы хотите быть действительно придирчивым к тому, чтобы не включать нижнюю часть записи после первого появления «VLC», тогда:

     pactl list sink-inputs | awk -v RS="" -v FS="\n" '/VLC/{ for(i=1; i<=NF; i++) { print $i; if($i ~ /VLC/) exit}}' 
    Linux и Unix - лучшая ОС в мире.