Shell

使用 awk、sed 或 grep 從文件中提取唯一的文本

  • December 6, 2015

從 的輸出中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)"

ed

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

它將r命令輸出讀入文本緩衝區,d刪除第一行匹配後的所有內容VLC,然後p從前一行匹配Sink Input到目前行。

sed

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

它將每一行附加到H舊緩衝區,如果一行匹配Sink Input,它會覆蓋h舊緩衝區,當一行匹配 VLC 時,它x會更改保持空間 w。模式空間、prints 和quits。

引用自:https://unix.stackexchange.com/questions/204392