首先,向stackoverflow社区问好。感谢非常明确的问题和专业的回复,我学到了很多东西。我从来不需要提问,因为以前总会有人问过同样的问题。
但不是今天。我没有找到解决问题的方法,我求求你的帮助。
我需要逐行处理函数的输出,以便在线更新日志。我正在使用bash
。
以下块效果很好:
convertor some parameters | while read line
do
if [ "${line:0:14}" != "[informations]" ]
then
update_online_log "${line}"
fi
done
但convertor
可能会以不同的状态退出。我需要知道什么是退出状态。下面的代码不起作用,因为它给出了上次执行的命令(update_online_log
)的退出状态。
convertor some parameters | while read line
do
if [ "${line:0:14}" != "[informations]" ]
then
update_online_log "${line}"
fi
done
exit_status=$?
下面的代码应该可以使用(我还没有尝试过):
convertor some parameters > out.txt
exit_status=$?
while read line
do
if [ "${line:0:14}" != "[informations]" ]
then
update_online_log "${line}"
fi
done < out.txt
rm out.txt
但如果我使用此功能,则会在转换结束时更新在线日志。转换可能是一个非常漫长的过程,我希望在转换过程中让用户保持更新。
提前感谢您的帮助。
答案 0 :(得分:1)
PIPESTATUS
数组可能对您有所帮助:它保存了上一个管道的每个组件的退出状态:
$ (echo a; exit 42) | (cat; echo b; exit 21) | (cat; echo c; exit 3) | { cat; echo hello; }
a
b
c
hello
$ echo "${PIPESTATUS[*]}"
42 21 3 0
那个数组非常脆弱,所以如果你想用它做什么,立即把它保存到另一个数组:
$ (echo a; exit 42) | ... as above
$ ps=( "${PIPESTATUS[@]}" )
$ for i in "${!ps[@]}"; do echo "$i ${ps[$i]}"; done
0 42
1 21
2 3
3 0
答案 1 :(得分:0)
在脚本顶部添加set -o pipefail
。来自文档:
管道的返回值是状态 以非零状态退出的最后一个命令, 如果没有以非零状态退出命令,则为零
这意味着如果所有命令都成功则为零,如果任何命令失败则为非零。
只需检查done
之后的退出状态即可。用
convertor some parameters | false | while read line
...
不应处理任何行,退出代码应为1
。
答案 2 :(得分:0)
作为符合POSIX标准的解决方案,并且为了表明您的方法接近工作,您可以使用命名管道而不是常规文件。
mkfifo out.txt
while read line; do
if [[ $line != \[informations\]* ]]; then
update_online_log "$line"
fi
done < out.txt &
convertor some parameters > out.txt
rm out.txt
此代码创建命名管道,然后运行在后台使用它的循环。它将阻止等待来自converter
的数据。退出converter
后(您可以在此时获取退出代码),out.txt
将关闭,while
循环进程将退出,您可以删除命名管道。