将标准输出捕获到变量并获取前台管道的退出状态
Capture stdout to variable and get the exit statuses of foreground pipe
我想执行一个命令(比如 ls
)并 sed
它的输出,然后将标准输出保存到一个变量中,像这样,
OUT=$(ls | sed -n -e 's/regexp/replacement/p')
在此之后,如果我尝试访问 $PIPESTATUS
数组,我只会得到 0
(与 $?
相同)。那么,如何获得 $PIPESTATUS
以及捕获整个管道命令的标准输出?
注:
- 如果我只执行那些管道命令而没有捕获标准输出(如
ls | sed -n -e 's/regexp/replacement/p'
),我将在 $PIPESTATUS
中获得预期的退出状态(如 0 0
)
- 如果我只使用 Command Substitution 执行单个命令(没有通过管道传输多个命令)并捕获标准输出(如
OUT=$(ls)
),我将得到 single $PIPESTATUS
中的退出状态(与 $?
相同)
P.S。我知道,我可以 运行 命令 2 次(第一次捕获标准输出,第二次访问 $PIPESTATUS
而不使用命令替换),但是有没有办法在一次执行中同时获得这两个命令?
您可以:
使用临时文件传递 PIPESTATUS。
tmp=$(mktemp)
out=$(pipeline; echo "${PIPESTATUS[@]}" > "$tmp")
PIPESTATUS=($(<"$tmp")) # Note: PIPESTATUS is overwritten each command...
rm "$tmp"
使用临时文件传递out
.
tmp=$(mktemp)
pipeline > "$tmp"
out=$(<"$tmp"))
rm "$tmp"
交错输出与管道状态。例如,为 PIPESTATUS 保留从最后一个换行符到结尾的部分。为了保留原始 return 状态,我认为需要一些临时变量:
out=$(pipeline; tmp=("${PIPESTATUS[@]}") ret=$?; echo $'\n' "${tmp[@]}"; exit "$ret"))
pipestatus=(${out##*$'\n'})
out="${out%$'\n'*}"
out="${out%%$'\n'}" # remove trailing newlines like command substitution does
测试:
out=$(false | true | false | echo 123; echo $'\n' "${PIPESTATUS[@]}");
pipestatus=(${out##*$'\n'});
out="${out%$'\n'*}"; out="${out%%$'\n'}";
echo out="$out" PIPESTATUS="${pipestatus[@]}"
# out=123 PIPESTATUS=1 0 1 0
备注:
- 按照惯例,大写变量应由导出变量保留。
我想执行一个命令(比如 ls
)并 sed
它的输出,然后将标准输出保存到一个变量中,像这样,
OUT=$(ls | sed -n -e 's/regexp/replacement/p')
在此之后,如果我尝试访问 $PIPESTATUS
数组,我只会得到 0
(与 $?
相同)。那么,如何获得 $PIPESTATUS
以及捕获整个管道命令的标准输出?
注:
- 如果我只执行那些管道命令而没有捕获标准输出(如
ls | sed -n -e 's/regexp/replacement/p'
),我将在$PIPESTATUS
中获得预期的退出状态(如0 0
) - 如果我只使用 Command Substitution 执行单个命令(没有通过管道传输多个命令)并捕获标准输出(如
OUT=$(ls)
),我将得到 single$PIPESTATUS
中的退出状态(与$?
相同)
P.S。我知道,我可以 运行 命令 2 次(第一次捕获标准输出,第二次访问 $PIPESTATUS
而不使用命令替换),但是有没有办法在一次执行中同时获得这两个命令?
您可以:
使用临时文件传递 PIPESTATUS。
tmp=$(mktemp) out=$(pipeline; echo "${PIPESTATUS[@]}" > "$tmp") PIPESTATUS=($(<"$tmp")) # Note: PIPESTATUS is overwritten each command... rm "$tmp"
使用临时文件传递
out
.tmp=$(mktemp) pipeline > "$tmp" out=$(<"$tmp")) rm "$tmp"
交错输出与管道状态。例如,为 PIPESTATUS 保留从最后一个换行符到结尾的部分。为了保留原始 return 状态,我认为需要一些临时变量:
out=$(pipeline; tmp=("${PIPESTATUS[@]}") ret=$?; echo $'\n' "${tmp[@]}"; exit "$ret")) pipestatus=(${out##*$'\n'}) out="${out%$'\n'*}" out="${out%%$'\n'}" # remove trailing newlines like command substitution does
测试:
out=$(false | true | false | echo 123; echo $'\n' "${PIPESTATUS[@]}"); pipestatus=(${out##*$'\n'}); out="${out%$'\n'*}"; out="${out%%$'\n'}"; echo out="$out" PIPESTATUS="${pipestatus[@]}" # out=123 PIPESTATUS=1 0 1 0
备注:
- 按照惯例,大写变量应由导出变量保留。