5

我真正想做的就是确保管道中的所有内容都成功并将最后一个标准输入分配给一个变量。考虑以下简化的场景:

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工作并将标准输入分配给变量的方法呢?

注意:这些示例被简化了。我并没有真正做 a或 a exit 1,而是使用这些命令进行简化,以便我们可以专注于我的特定问题。echo 1cat

4

6 回答 6

3

当您使用反引号(或首选$())时,您正在子shell 中运行这些命令。PIPESTATUS你得到的是分配而不是子shell中的管道命令。

当您使用xargs时,它对外壳一无所知,因此无法进行变量赋值。

尝试set -o pipefail然后您可以从中获取状态$?

于 2010-08-10T21:03:57.823 回答
3

xargs在子进程中运行,您调用的所有命令也是如此。所以他们不能影响你的外壳环境。

您可能可以使用命名管道 ( mkfifo) 或可能的 bashread函数来做一些事情?

编辑:

也许只是将输出重定向到一个文件,然后你可以使用 PIPESTATUS:

command1 | command2 | command3 >/tmp/tmpfile
## Examine PIPESTATUS
X=$(cat /tmp/tmpfile)
于 2010-08-10T16:27:15.290 回答
0

怎么样 ...

read x <<<"$(echo 1)"
read x < <(echo 1)

echo "$x"
于 2010-08-10T21:10:32.760 回答
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]}"
于 2010-08-11T10:46:00.840 回答
0

已经有一些有用的解决方案。事实证明,我实际上有一个与上述问题相匹配的示例;无论如何,足够接近。

考虑一下:

 XX=$(ls -l *.cpp | wc -l  | xargs -I{} echo {})
 echo $XX
 3

这意味着.cpp我的工作目录中有 3 个文件。现在$XX是 3,我可以在我的脚本中使用该结果。xargs这是人为的,因为在这个例子中我实际上并不需要。它虽然有效。

在问题的示例中...

x=`exit 1|cat`

我认为这不会给您指定的内容。 将在提及exit之前退出子外壳。cat也在那张纸条上,

我可能会从类似的东西开始

declare -a PIPESTATUS='([0]="0")'
x=$?

x现在具有上一个命令的状态。

于 2018-11-20T12:51:17.180 回答
0

将每一行输入分配给一个数组,例如一个目录中的所有 python 文件

declare -a pyFiles=($(ls -l *.py | awk '{print $9}')) 

其中 $9 是 ls -l 中对应于文件名的第九个字段

于 2019-12-17T18:38:22.737 回答