Bash 如何逐行处理输出并保存返回状态?
首先,大家好,stackoverflow社区。我学到了很多,这要感谢非常清晰的问题和专业的回答。我从来不需要问问题,因为总有人问过同样的问题 但今天不行。我还没有找到解决我问题的办法,我请求你的帮助。 我需要逐行处理函数的输出,以便在线更新日志。我正在使用Bash 如何逐行处理输出并保存返回状态?,bash,Bash,首先,大家好,stackoverflow社区。我学到了很多,这要感谢非常清晰的问题和专业的回答。我从来不需要问问题,因为总有人问过同样的问题 但今天不行。我还没有找到解决我问题的办法,我请求你的帮助。 我需要逐行处理函数的输出,以便在线更新日志。我正在使用bash 下面的块工作得很好: convertor some parameters | while read line do if [ "${line:0:14}" != "[informations]" ] then
bash
下面的块工作得很好:
convertor some parameters | while read line
do
if [ "${line:0:14}" != "[informations]" ]
then
update_online_log "${line}"
fi
done
但是,转换器
可能以不同的状态退出。我需要知道什么是退出状态。下面的代码不起作用,因为它提供了上次执行的命令的退出状态(update\u online\u log
)
下面的代码应该可以工作(我还没有尝试过):
转换器某些参数>out.txt
退出状态=$?
读行时
做
如果[“${line:0:14}”!=“[信息]”]
然后
更新联机日志“${line}”
fi
done
但是如果我使用这个,在线日志将在转换结束时更新。转换可能是一个很长的过程,我希望在转换过程中不断更新用户
提前感谢您的帮助。在脚本顶部添加
set-o pipefail
。从文件中:
管道的返回值是管道的状态
以非零状态退出的最后一个命令,
如果没有命令以非零状态退出,则为零
这意味着,如果所有命令都成功,则为零;如果任何命令失败,则为非零
只要在完成后检查退出状态就可以了。测试一下
convertor some parameters | false | while read line
...
不应处理任何行,并且退出代码应为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
作为与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
mkfifo out.txt
读行时;做
如果[[$line!=\[informations\]*];然后
更新联机日志“$line”
fi
doneout.txt
rm out.txt
这段代码创建命名管道,然后在后台运行使用它的循环。它将阻止等待来自转换器的数据。一旦converter
退出(此时您可以获取其退出代码),out.txt
将关闭,while
循环进程将退出,您可以删除命名管道。请看哇,这太快了!非常感谢,这正是我所需要的!这正是我想要的。谢谢:)
$ (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
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