sed -n -e 's

问题描述 投票:3回答:1

我想执行一个命令(比如说 ls)和 sed 的输出,然后将stdout保存到一个变量中,像这样。

OUT=$(ls | sed -n -e 's/regexp/replacement/p')

在这之后,如果我试图访问 $PIPESTATUS 数组,我只得到 0 宛如 $?). 那么,我如何才能同时获得 $PIPESTATUS 以及捕获整个管道命令的stdout?

请注意。

  • 如果我只执行了那些管道命令,而没有捕获stdout(如 ls | sed -n -e 's/regexp/replacement/p'),我在 $PIPESTATUS (像 0 0)
  • 如果我只执行单条命令(不需要管道式的多条命令),使用的是 命令替换 并捕捉到了stdout(像 OUT=$(ls)),我得到的预期是 单一 退出状态 $PIPESTATUS 宛如 $?)

P.S. 我知道,我可以运行2次命令(第一次捕获stdout,第二次访问 $PIPESTATUS 而不使用命令替换),但是有什么方法可以在一次执行中同时获得这两个命令?

bash shell pipe stdout exit-code
1个回答
2
投票

你可以这样做。

  1. 用一个临时文件来传递PIPESTATUS。

    tmp=$(mktemp)
    out=$(pipeline; echo "${PIPESTATUS[@]}" > "$tmp")
    PIPESTATUS=($(<"$tmp"))  # Note: PIPESTATUS is overwritten each command...
    rm "$tmp"
    
  2. 使用一个临时文件来传递PIPESTATUS。out.

    tmp=$(mktemp)
    pipeline > "$tmp"
    out=$(<"$tmp"))
    rm "$tmp"
    
  3. 将输出与pipestatus交错。例如,从最后一个换行符到最后的部分保留给PIPESTATUS。为了保留原始的返回状态,我认为需要一些临时变量。

    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
    

注意:

  • 按照惯例,大写变量应该由输出变量保留。
© www.soinside.com 2019 - 2024. All rights reserved.