逐条管道

逐条管道

我有一个“监听”amixer事件(音量变化和静音)的脚本,通过管道将音量和静音状态传递给xob。它工作得很好,但是(滥用)stdbuf -oL <command>对我来说看起来是错误的,我想知道是否还有其他方法可以做我想做的事情。我想我正在寻找一种方法来使脚本中的每个命令都进行行缓冲。

尽管这个脚本并不那么便携,但可移植的答案值得赞赏。

我是 shell 脚本编写的新手,因此特别感谢对该脚本的其他改进!

这是脚本:

#!/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您也可以在 shell 中轻松执行和 过滤,因此:

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

相关内容