我正在尝试在bash中编写简单的通知应用程序。我想从mplayer读取输出,解析它并通过notify-send显示。
我可以使用以下方法从mplayer获得所需的信息:
mplayer <url> | grep ICY
然后使用sed解析。
我创建命名管道,告诉mplayer写它然后我正在读它。不幸的是,它不起作用。这是我的剧本:
$fifo=~/.rp/fifo
mkfifo $fifo
mplayer <url> 2>/dev/null | grep ICY 1> $fifo &
while read line < $fifo; do
echo $line
done
wait
程序一直在等待从$ fifo输入。我尝试在其他终端中关注,而此脚本正在运行:
运行
echo "Test" > .rp/fifo
带有运行脚本的终端显示“测试”
运行
echo "ICY" | grep ICY > .rp/fifo
也有效。
运行
mplayer <url> | grep ICY > .rp/fifo
不工作。
我上面说过,mplayer的组合| grep工作得很好。 grep&gt; $ fifo工作正常。我不明白为什么mplayer | grep&gt; $ fifo不起作用。
答案 0 :(得分:5)
我怀疑您可能正在体验C库的流的完全缓冲模式。您没有说您正在运行GNU用户空间,但如果您正在运行,则可以查看stdbuf(1)
以修改缓冲区域。
您可以尝试首先仅grep
作为stdbuf(1)
的孩子运行,如下所示:
mplayer <url> | stdbuf -o L grep ICY > .rp/fifo
如果这不起作用,那就是呐喊!
stdbuf -o 0 mplayer <url> | stdbuf -o L grep ICY > .rp/fifo
如果仍然不起作用,那么mplayer
可能不会写入stdout,而是直接写入/dev/tty
。在这种情况下,您需要阅读expect(1)
。
答案 1 :(得分:3)
你可以用:
做无缓冲的grep$ mplayer ... 2>&1 | grep --line-buffered "ICY"
或更好:
$ mplayer ... 2>&1 | sed -une 's/^.*ICY[^:]*: //p'
甚至,为什么不呢(sed非常适合grep和格式化),
这将会导致ICY
行,甚至包含-
的第一个字段中包含:
的分割线,该字符长度来自第二个字段的$ mplayer ... 2>&1 |
sed -une "
/ICY/{
s/^.*ICY[^:]*:.*'\([^']*\)';/\1/;
s/^\(.*\) - /\1 - /;
s/^\(.\{30\}\) *- /\1: /;
p;
}"
:
Artist name : Song title
Other artist : Other song
Unsplited line
Artist : Title
可以给出类似的东西:
{{1}}
答案 2 :(得分:0)
我使用FIFO文件在slave模式下启动mplayer。
mkfifo /tmp/mpfifo
mplayer -slave -input file=/tmp/mpfifo video.mp4
我可以从另一个终端控制视频播放器。
echo "pause" >> /tmp/mpfifo
echo "volume 50" > /tmp/mpfifo
我想获得价值(例如播放视频的当前位置)。所以我试过了:
echo "get_time_pos" > /tmp/mpfifo
但没有返回任何价值。 我搜索了几个小时,但没有成功。 然后我想把mplayer输出重定向到一个文件:
mplayer -slave -input file=/tmp/mpfifo video.mp4 > /tmp/mpout.txt
之后执行以下命令时:
echo "get_time_pos" > /tmp/mpfifo
echo "get_property length" > /tmp/mpfifo
/tmp/mpout.txt中的输出如下:
.......
.......
ANS_TIME_POSITION=113.6
ANS_length=2534.602031
如果每个命令的结果都返回到命令行会非常好。即使它可能需要一些工作,但是可以解析输出文件。