パイプライン別パイプライン

パイプライン別パイプライン

イベント(音量変更とミュート)を「受信」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。出力を1行ずつバッファリングするように指示します。

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

おすすめ記事