Linux bash 스크립트에서 명령의 결과 구문 분석하기


1

필자는 Pulseaudio 입력 / 출력을 제어하기 위해 Linux에 작은 bash 스크립트를 작성하고 있습니다.

내가하고 싶은 일은 하나를 제외한 모든 싱크 입력을 하나 또는 다른 싱크대로 라우팅하는 것입니다. 나가고 싶지 않은 싱크 입력은 다음과 같습니다.

pi@raspberrypi:~/fonction $ pactl list sink-inputs
Sink Input #36062
    Driver: protocol-native.c
    Owner Module: 2
    Client: 198
    Sink: 2
    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: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
            balance 0.00
    Buffer Latency: 120000 usec
    Sink Latency: 236349 usec
    Resample method: n/a
    Properties:
        media.name = "ALSA Playback"
        application.name = "ALSA plug-in [snapclient]"
        native-protocol.peer = "UNIX socket client"
        native-protocol.version = "32"
        application.process.id = "539"
        application.process.user = "snapclient"
        application.process.host = "raspberrypi"
        application.process.binary = "snapclient"
        application.language = "C"
        application.process.machine_id = "69e523231bb44f2e926a758a63cbb5b1"
        module-stream-restore.id = "sink-input-by-application-name:ALSA plug-in [snapclient]"

싱크 입력을 다른 싱크로 이동하려면이 명령을 사용해야합니다.

pactl move-sink-input <sink-input id> <sink id>

그래서 첫 번째 명령의 결과를 파싱하여 Sink Input #ID (첫 번째 줄에 포함되어 있음)하지만 조건을 사용하여 확인해야합니다. module-stream-restore.id (마지막 줄)은 실제로 내가 원하는 경로입니다.

나는 다음과 같은 것을 필요로 할 것이다 :

if [ <last line> = 'sink-input name I need' ] 
then
  pactl move-sink-input <id from first line> <my sink name>
fi

난 그냥 두 가지 정보를 얻으려면 명령을 구문 분석하는 방법을 모르겠다.

지금 당장은 마지막 줄이나 #ID 만 얻을 수 있습니다.

 pactl list short sink-inputs|while read stream; do
    streamId=$(echo $stream )
    id=$(echo pactl list sink-inputs | grep module-stream-restore.id | grep -o '".*"' |sed 's/"//g')

    if [ "$streamId" != 'sink-input-by-application-name:ALSA plug-in [snapclient]' ]
    then
        pactl move-sink-input "$streamId" Snapcast
    fi

결과를 파싱하려면 어떻게해야합니까? pactl list sink-inputs 그래서 나는 bash 스크립트에서 그 명령의 결과의 각 "블록"(일명, 각 싱크 - 입력)에서 단지 하나가 아닌 두 가지 요소를 읽을 수 있습니까?


왜 싱크 입력 번호를 변수에 저장하지 않습니까?
Nifle

첫 번째 줄과 마지막 줄은 head -n1tail -n1 또는 sed '1!d'sed '$!d'
Paulo

@Nifle, 싱크 입력 번호는 언제든지 바뀔 수 있습니다.
Gob Tron

@Paulo, 오늘 밤 한번 시도해 볼게. 그것은 내가 필요한 것일지도 모른다.
Gob Tron

답변:


2

문제는 변수가 do 루프가 한 패스에서 다음 패스로 유지되지 않습니다.

간단한 해결책은 목록 출력을 임시 파일에 저장 한 다음 두 번 스캔하는 것입니다.

pactl list short sink-inputs >temp.lst
streamId=$(sed -n 's/^Sink Input #\(.*\)$/\1/p' <temp.lst)
id=$(sed -n 's/.*module-stream-restore.id = "\(.*\)"$/\1/p' <temp.lst)
rm temp.lst 

이제 두 변수를 설정해야합니다. 매우 세련된 솔루션은 아니지만 이해하기 쉽고 간단합니다. 나는 sed 수행하기 grep 함수 : 어떻게 작동하는지에 대한 안내는 이리 .

그러나 임시 파일을 회 피한 솔루션으로 피할 수 있습니다.

Ids="$(pactl list short sink-inputs | \
       sed -n -e 's/^Sink Input #\(.*\)$/\1/p' \
              -e 's/.*module-stream-restore.id = "\(.*\)"$/\1/p')"

이제 두 변수가 모두 Ids, 줄 바꿈으로 구분 : 당신은 함께 그들을 나눌 수 있습니다 : -

streamId="${Ids%$'\n'*}"
Id="${Ids#*$'\n'}"

임시 변수가 마음에 들지 않으면 다음 중 하나를 사용하십시오. Id 대신에 Ids!

필자는 목록 출력을 복사하고이를 실제 대신 사용하여 테스트했습니다. pactl 명령이므로 라이브 명령으로 모두 작동해야합니다.


2

개념:

  1. 호출 pactl …LC_ALL=C 지역화 된 출력을 피하기 위해 설정합니다 (분명히 필요하지는 않지만 일반적으로 사람들이 사용합니다).
  2. 용도 egrep 관련없는 선을 버리기. 다음과 같이 쌍을 이루고 싶습니다.

    Sink Input #12345
            module-stream-restore.id = "whatever"
    
  3. 라인이 쌍으로 있다고 가정하면, read 그들과 함께 2 명씩 2 명씩 IFS ( # 한 쌍의 첫 번째 줄은 = 둘째) 관련 데이터를 추출합니다. 필요없는 부분에는 더미 변수를 사용하십시오.

  4. 추출 된 데이터로 작업하십시오. 유의 사항 IFS='=' 한 쌍의 두 번째 줄은 =, 즉 인접한 공간과 큰 따옴표도 포함합니다. 이것이 (아래) 코드에서 나는 ' "sink-… [snapclient]"', 뿐만 아니라 'sink-… [snapclient]'.

코드:

LC_ALL=C pactl list sink-inputs |
egrep "^Sink Input #|module-stream-restore.id = " |
while IFS='#' read dummy id && IFS='=' read dummy restid; do
 if [ "$restid" = ' "sink-input-by-application-name:ALSA plug-in [snapclient]"' ] ; then
  printf 'Match for ID %s.\n' "$id"
  # do something
 else
  printf 'No match for ID %s.\n' "$id"
  # do something else
 fi
done
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.