Извлечение уникальной части текста из файла с помощью 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)" 

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}}' 
  • Удалить строку, если два шаблона найдены в одной строке
  • Печатать начало и конец между двумя шаблонами, исключая конец диапазона
  • Сокращение порядка и вывод текста
  • Каковы альтернативные инструменты для поиска файлов в полном объеме?
  • Как заполнить конечные теги с помощью sed, awk или любой другой команды?
  • захватить текст из файла vtt
  • Найти и заменить слова в текстовом файле рекурсивно
  • Удалить строки из файла в зависимости от строк, найденных в другом файле
  • Удалить до первого вхождения, отредактировать эту строку и распечатать оставшиеся строки без изменений
  • использование sed для замены шаблона с помощью хэш-значений
  • Как прочитать файл свойств через мой скрипт?
  • Как получить путь, индекс строки и содержимое строки в оболочке bash?
  • Interesting Posts
    Linux и Unix - лучшая ОС в мире.