使用 xargs 将 stdin 分配给变量

发布于 2024-09-13 17:16:14 字数 800 浏览 7 评论 0原文

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

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

注意:这些例子是简化的。我并没有真正执行 exit 1echo 1cat,而是使用这些命令进行简化,以便我们可以专注于我的特定操作问题。

All that I really want to do is make sure everything in a pipeline succeeded and assign the last stdin to a variable. Consider the following dumbed down scenario:

x=`exit 1|cat`

When I run declare -a, I see this:

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

I need some way to notice the exit 1, so I converted it to this:

exit 1|cat|xargs -I {} x={}

And declare -a gave me:

declare -a PIPESTATUS='([0]="1" [1]="0" [2]="0")'

That is what I wanted, so I tried to see what would happen if the exit 1 didn't happen:

echo 1|cat|xargs -I {} x={}

But it fails with:

xargs: x={}: No such file or directory

Is there any way to have xargs assign {} to x? What about other methods of having PIPESTATUS work and assigning the stdin to a variable?

Note: these examples are dumbed down. I'm not really doing an exit 1, echo 1 or a cat, but used these commands to simplify so we can focus on my particular issue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

念三年u 2024-09-20 17:16:14

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

当您使用 xargs 时,它对 shell 一无所知,因此无法进行变量分配。

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

When you use backticks (or the preferred $()) you're running those commands in a subshell. The PIPESTATUS you're getting is for the assignment rather than the piped commands in the subshell.

When you use xargs, it knows nothing about the shell so it can't make variable assignments.

Try set -o pipefail then you can get the status from $?.

无需解释 2024-09-20 17:16:14

xargs 与您调用的所有命令一样在子进程中运行。所以它们不会影响你的 shell 的环境。

您也许可以使用命名管道 (mkfifo) 或 bash 的 read 函数来执行某些操作?

编辑:

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

command1 | command2 | command3 >/tmp/tmpfile
## Examine PIPESTATUS
X=$(cat /tmp/tmpfile)

xargs is run in a child process, as are all the commands you call. So they can't effect the environment of your shell.

You might be able to do something with named pipes (mkfifo), or possible bash's read function?

EDIT:

Maybe just redirect the output to a file, then you can use PIPESTATUS:

command1 | command2 | command3 >/tmp/tmpfile
## Examine PIPESTATUS
X=$(cat /tmp/tmpfile)
流年里的时光 2024-09-20 17:16:14

怎么样...

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

echo "$x"

How about ...

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

echo "$x"
燃情 2024-09-20 17:16:14

为什么不直接填充一个新数组呢?

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]}"

Why not just populate a new array?

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]}"
庆幸我还是我 2024-09-20 17:16:14

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

考虑一下:

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

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

在问题的示例中......

x=`exit 1|cat`

我认为这不会给您指定的内容。 exit 将在 cat 被提及之前退出子 shell。另外,

我可能会从类似

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

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

There are already a few helpful solutions. It turns out that I actually had an example that matches the question as framed above; close-enough anyway.

Consider this:

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

Meaning that I had 3 x .cpp files to in my working directory. Now $XX is 3 and I can make use of that result in my script. It is contrived, because I don't actually need the xargs in this example. It works though.

In the example from the question ...

x=`exit 1|cat`

I don't think that will give you what was specified. exit will quit the sub-shell before the cat gets a mention. Also on that note,

I might start with something like

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

x now has the status from the last command.

指尖微凉心微凉 2024-09-20 17:16:14

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

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

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

Assign each line of input to an array, e.g. all python files in a directory

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

where $9 is the nineth field in ls -l corresponding to the filename

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文