파이프라인별 파이프라인

파이프라인별 파이프라인

이벤트(볼륨 변경 및 음소거)를 "수신" amixer하고 볼륨 및 음소거 상태를xob. 잘 작동하지만 (오용이) stdbuf -oL <command>잘못된 것 같고 내가 원하는 것을 수행할 수 있는 다른 방법이 있는지 궁금합니다. 나는 스크립트 줄의 모든 명령을 버퍼링하는 방법을 찾고 있다고 생각합니다.

이 스크립트는 이식성이 높지는 않지만 이식 가능한 답변에 감사드립니다.

저는 쉘 스크립팅이 처음이므로 이 스크립트에 대한 추가 개선 사항이 특히 감사하겠습니다!

스크립트는 다음과 같습니다.

#!/bin/sh

# Wait for amixer to become available
until [ "$(amixer)" ]; do sleep 0.1; done

get_volume () {
    OUT=$(amixer sget Master)
    VOLUME=$(echo $OUT | awk -F"[][]" '/Left:/ { print $2 }' | tr -d '%')
    STATE=$(echo $OUT | awk -F"[][]" '/Left:/ { print $4 }')

    [ "$STATE" = "off" ] && VOLUME="$VOLUME!"

    echo $VOLUME
}

stdbuf -oL amixer events \
    | stdbuf -oL grep -E "event value: numid=(3|4)" \
    | stdbuf -oL tail -n +2 \
    | while read REPLY; do get_volume; done \
    | xob

감사해요!

답변1

GNU grep(가 있는 시스템에 있음 amixer)에는 옵션이 있습니다 --line-buffered. 출력을 한 줄씩 버퍼링하도록 지시합니다.

tail -n+2또한 셸에서 쉽게 수행하고 필터링할 수 있으므로 다음과 같습니다.

get_volume() {
  amixer sget Master |
    awk -F'[][]' '/Left:/ {print 0+$2 ($4 == "off" ? "!" : "")}'
}

skip=1
stdbuf -oL amixer events |
  while IFS= read -r line; do
    case ${line%%,*} in
      ('event value: numid='[34])
        if [ "$skip" -eq 0 ]; then
          get_volume
        else
          skip=$(( skip - 1 ))
        fi
    esac
  done | xob

관련 정보