在bash中如何parsing和/或redirect标准输出的任意程序,我是背景

在之前的一个问题中,我问如何写一个程序的标准input。 这个问题是build立在这个问题上的。 现在我问“如何parsing我所调用的程序的输出”。

在这个例子中,我正在调用一个我可以编辑的程序(Sum.sh),这个问题与这个问题无关。 我想要这种行为,如果我不能控制我正在调用的程序的实现。 我想要“replace”一个程序期望的物理人,并通过脚本来驱动它。

给定两个脚本
Sum.sh:

#!/bin/bash sum=0 inp=0 while true; do printf "Sum: %d\n" $sum printf "Give me an integer: " read inp if [ "$inp" == 0 ]; then exit fi sum=$((sum+inp)) done 

和driver.sh:

 #!/bin/bash rm -f /tmp/sumpipe mkfifo /tmp/sumpipe ./Sum.sh < /tmp/sumpipe & echo 2 > /tmp/sumpipe echo 5 > /tmp/sumpipe echo 0 > /tmp/sumpipe sleep 1 # this is required for some reason or the script hangs 

我运行driver.sh我得到以下内容:

 $ ./driver.sh Sum: 0 Give me an integer: Sum: 2 Give me an integer: Sum: 7 Give me an integer: $ 

terminal输出的格式对这个问题并不重要。

我想要做的就是parsing所说的输出,以便在driver.sh中作出决定。 在下面的driver.sh的伪代码中,我试图展示我想要做的事情:

 #!/bin/bash rm -f /tmp/sumpipe mkfifo /tmp/sumpipe output=$(./Sum.sh < /tmp/sumpipe &) while true; do if [ "$output" != empty ]; then (make some decision based on what output is and echo back to my process if necessary) fi done 

不幸的是, $output从不包含任何东西,我已经尝试了许多版本的滥用 读取和pipe道,并没有一个在我的应用程序工作。 我怎样才能redirect我的后台程序的标准输出,所以我可以parsing它?


我尝试了OrangesV提出的解决scheme(并遵从William Pursell关于out buffer太空的build议),并提出以下build议:

 #!/bin/bash rm -f /tmp/sumpipe mkfifo /tmp/sumpipe while read output; do echo "2347823" > /tmp/sumpipe if [ -z $output ]; then continue else echo "got it!" echo $output sleep 1 fi done < <(./Sum.sh < /tmp/sumpipe &) 

不幸的是,“明白了!” 从来没有回应,所以它似乎没有工作。

如果是相关的,我的bash版本:

 $ bash --version GNU bash, version 4.4.0(7)-rc2 (x86_64-unknown-linux-gnu) 

现在有一个部分的解决scheme。 Diego Torres Milano的答案确实有效。 但是,我的stdio被缓冲,所以我不会得到任何东西,直到stdio至less有4096字节在里面。 我可以使用以下版本的driver.sh强制输出:

 #!/bin/bash inpipe=/tmp/sumpipei outpipe=/tmp/sumpipeo rm -f $inpipe rm -f $outpipe mkfifo $inpipe mkfifo $outpipe ./Sum.sh < $inpipe > $outpipe & count=0 while true; do while read line do echo "line=$line" done < $outpipe & echo 2 > $inpipe done 

我尝试了各种stdbuf的调用(比如: stdbuf -o0 ./Sum.sh <$inpipe > $outpipe & )。 stdbuf在这种情况下显然不起作用,强制closures缓冲区,因为根据stdbufcommandstdbuf option… command的GNU coreutils手册stdbuf option… command

命令必须以一个程序的名字开始,这个程序不会调整标准stream的缓冲(注意程序T不在这个范畴)。

不幸的 ,我正在这里做什么。

我认为迭戈的答案是正确的,即使它在stdio缓冲区问题得到解决之前无法正常工作。 我会提出下一个问题来解决stdio缓冲问题。 我几乎可以在这里品尝到奖品。

使用另一个管道输出

 mkfifo /tmp/output ./Sum.sh < /tmp/sumpipe > /tmp/output & 

你可以用它来处理它

 while read line do echo "line=$line" done < /tmp/output & 

你可以在你的driver.sh中while read一段时间。

 while read output; do if [ "${output}" == "something" ]; then #do something fi done < <(./Sum.sh < /tmp/sumpipe &) 

编辑

这个循环不会开始迭代,直到脚本的stdin接收输入。 所以,在另一个shell /进程echo # > /tmp/sumpipe