2

我正在尝试运行一个命令并将它的输出保存到一个变量中(这样我以后可以解析它并从输出中提取信息)。我知道如何将它保存到一个变量中,但我希望它显示即将到来的输出,不仅在最后,所以我可以看到正在执行的输出。或者更好的是,能够显示它,并使用该信息过滤/执行其他命令。

我以为我可以以某种方式将命令导入read,但无法使其正常工作。

这是我一直在使用的示例代码:

#!/bin/bash

count=0
function theloop() {
        while [ $count -lt 10 ]; do
                echo "the count is $count"
                sleep 1
                let count=count+1
        done
}

output=$(theloop)

echo "the output was:"
echo "$output"

这会输出计数,但仅在最后更新,而不是每秒写入一行。

有人可以告诉我如何将循环输入read或其他解决方案。即使只是将它保存到一个我可以稍后解析的变量中也会很好,只要屏幕在生成计数时每秒更新一次。

我想我可以以某种方式使用tee到一个临时文件中,然后阅读它,但这对我来说似乎是一个不雅的解决方案。

编辑:我应该提到我计划在另一个我不够聪明无法编辑的程序的输出上使用它,所以我宁愿回答不改变theloop()功能的答案。

4

3 回答 3

3

而不是teeing 输出到一个临时文件中,您可以将tee其转换为/dev/tty. 说

output=$(theloop | tee /dev/tty)

代替

output=$(theloop)

并且您将在显示时将输出放入变量中。


编辑:根据您的评论,如果您只想在控制台中显示计数 7,但将所有输出保存到变量中,您可以说:

count=0
function theloop() {
        while [ $count -lt 10 ]; do
                [ $count -eq 7 ] && { echo "the count is $count" | tee /dev/tty; } || echo "the count is $count"
                sleep 1
                let count=count+1
        done
}

output=$(theloop)

echo "the output was:"
echo "$output"

请注意,tee现在已在函数内部移动。本质上,你tee有条件地,同时继续echo一切。

如果你不能改变功能,你可以说:

while read -r line; do
  output+="${line}\n"
  [[ $line == *7* ]] && echo ${line}
done < <(theloop)

echo "the output was:"
echo -e "${output}"
于 2013-11-09T07:21:04.827 回答
1

这不使用临时文件,而是使用临时命名管道 (fifo),它不占用磁盘空间(另外,我在 ramdisk 上创建它,因此它甚至不接触磁盘)。

#!/bin/bash

count=0
function theloop() {
        while [ $count -lt 10 ]; do
                echo "the count is $count"
                sleep 1
                let count=count+1
        done
}

fifo=/dev/shm/foo
rm -f $fifo
mkfifo $fifo
cat <$fifo & output=$(theloop|tee $fifo)
rm $fifo

echo "the output was:"
echo "$output"
于 2013-11-09T07:26:15.563 回答
1

嗯,你已经说了。为什么不将输出通过管道传输到 read 中,如下所示:

theloop | while read line; do echo $line and do something with it;done

但是请注意,您可能无法在读取循环中设置变量,以便在循环之后可以看到它们,因为管道符号之后的部分在子外壳中运行。

于 2013-11-09T07:30:47.430 回答