我真正想做的就是确保管道中的所有内容都成功并将最后一个stdin分配给变量。考虑以下愚蠢的情景:
x=`exit 1|cat`
当我运行declare -a
时,我看到了这一点:
declare -a PIPESTATUS='([0]="0")'
我需要某种方式来注意exit 1
,所以我把它转换成了这个:
exit 1|cat|xargs -I {} x={}
declare -a
给了我:
declare -a PIPESTATUS='([0]="1" [1]="0" [2]="0")'
这就是我想要的,所以我试着看看如果exit 1
没有发生会发生什么:
echo 1|cat|xargs -I {} x={}
但它失败了:
xargs: x={}: No such file or directory
有没有办法让xargs将{}
分配给x
?那么让PIPESTATUS
工作并将stdin分配给变量的其他方法呢?
注意:这些例子都是愚蠢的。我实际上并不是exit 1
,echo 1
或cat
,而是使用这些命令进行简化,以便我们专注于我的特定问题。
答案 0 :(得分:3)
xargs
在子进程中运行,就像您调用的所有命令一样。所以它们不会影响shell的环境。
您可以使用命名管道(mkfifo
)或可能的bash read
函数执行某些操作吗?
编辑:
也许只是将输出重定向到文件,然后你可以使用PIPESTATUS:
command1 | command2 | command3 >/tmp/tmpfile
## Examine PIPESTATUS
X=$(cat /tmp/tmpfile)
答案 1 :(得分:3)
使用反引号(或首选的$()
)时,您将在子shell中运行这些命令。你获得的PIPESTATUS
是用于赋值而不是子shell中的管道命令。
使用xargs
时,它对shell一无所知,因此无法进行变量赋值。
尝试set -o pipefail
,然后您就可以从$?
获取状态。
答案 2 :(得分:0)
怎么样......
read x <<<"$(echo 1)"
read x < <(echo 1)
echo "$x"
答案 3 :(得分:0)
为什么不填充一个新阵列?
IFS=$'\n' read -r -d '' -a result < <(echo a | cat | cat; echo "PIPESTATUS='${PIPESTATUS[*]}'" )
IFS=$'\n' read -r -d '' -a result < <(echo a | exit 1 | cat; echo "PIPESTATUS='${PIPESTATUS[*]}'" )
echo "${#result[@]}"
echo "${result[@]}"
echo "${result[0]}"
echo "${result[1]}"
答案 4 :(得分:0)
已经有一些有用的解决方案。事实证明,我实际上有一个与上述问题相匹配的示例。足够接近 。
考虑一下:
XX=$(ls -l *.cpp | wc -l | xargs -I{} echo {})
echo $XX
3
这意味着我的工作目录中有3 x .cpp
个文件。现在$XX
是3,我可以在脚本中使用该结果。这是人为的,因为在此示例中,我实际上不需要xargs
。虽然可以。
在问题示例中...
x=`exit 1|cat`
我认为这不会给您指定的内容。 exit
将在cat
被提及之前退出子外壳。此外,
我可能会以类似的方式开始
declare -a PIPESTATUS='([0]="0")'
x=$?
x
现在具有上一条命令的状态。
答案 5 :(得分:0)
将输入的每一行分配给一个数组,例如目录中的所有python文件
declare -a pyFiles=($(ls -l *.py | awk '{print $9}'))
其中$ 9是ls -l中与文件名相对应的第九个字段