4

From the output of pactl list sink-inputs, I need to grab the sink input number for VLC. Before that, I'm trying to extract the piece that contains the output for only VLC. All the methods that I thought would work have shortcomings. This is a sample output:

$ 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"

Both awk '/^Sink/,/VLC/' and sed -n '/^Sink/,/VLC/p' grab the VLC part, but then grab the mplayer2 part too and go until the end of the output:

$ 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' works, but if the VLC output should come after mplayer2, it would fail (a test with mplayer2 instead of 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

The desired output:

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 Answers 3

7

With ed:

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

It reads the command output into the text buffer, deletes everything after the first line matching VLC and then prints from the previous line matching Sink Input up to current line.

With sed:

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

It appends each line to Hold buffer, if a line matches Sink Input it overwrites the hold buffer and when a line matches VLC it exchanges the hold space w. pattern space, prints and quits.

0
6

I'd use Perl's paragraph mode:

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

The -00 sets the input record separator to \n\n so a "line" is a paragraph. Then, the substitution will match everything until the first VLC and then anything until the 1st newline and save them as $1. Everything after that is removed (since we're replacing everything with $1). Finally, "lines" where that substitution was successful are printed.

0
3

These are effectively multi-line records separated by a blank line. Awk is great for handling this kind of data:

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

If you want to be really nit-picky about not including the bottom part of the record after the first occurrence of "VLC", then:

pactl list sink-inputs | awk -v RS="" -v FS="\n" '/VLC/{ for(i=1; i<=NF; i++) { print $i; if($i ~ /VLC/) exit}}' 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.