gpt4 book ai didi

Bash:将内置的 'times' 的输出分配给变量

转载 作者:行者123 更新时间:2023-11-29 08:57:27 29 4
gpt4 key购买 nike

bash 脚本中,我想将 times 内置函数的输出分配给一个数组变量,但我发现没有比

更好的方法了
tempnam=/tmp/aaa_$$_$RANDOM
times > ${tempnam}
mapfile -t times_a < ${tempnam}

我将输出写入一个临时文件并在数组 times_a 中读回它,因为管道或 $(times) 会在子 shell 中执行并返回错误的值。

没有临时文件有更好的解决方案吗?

最佳答案

您需要解决的根本问题是如何在同一个 shell 中同时执行 time 和变量赋值,而无需临时文件。几乎 Bash 提供的每一种方法,将一个事物的输出通过管道传输到另一个事物,或捕获命令的输出,都有一方在子 shell 中工作。

这是一种不需要临时文件就可以做到的方法,但我要警告你,它不漂亮,不能移植到其他 shell,而且它至少需要 Bash 4:

coproc co { cat; }; times 1>&${co[1]}; eval "exec ${co[1]}>&-"; mapfile -tu ${co[0]} times_a

我会为你分解一下:

coproc co { cat; }

这会创建一个协程;一个在后台运行的进程,但是你可以通过管道与它的标准输入和标准输出进行通信,它们是 FDs ${co[0]}(标准输出 cat) 和 ${co[1]}(cat 的标准输入)。命令在子 shell 中执行,所以我们不能在那里完成我们的任何一个目标(运行 times 或读入变量),但我们可以使用 cat 来只需将输入传递到输出,然后使用该管道与当前 shell 中的 timesmapfile 对话。

times >&${co[1]};

运行 times,将其标准输出重定向到 cat 命令的标准输入。

eval "exec ${co[1]}>&-"

关闭cat命令的输入端。如果我们不这样做,cat 将继续等待输入,保持其输出打开,而 mapfile 将继续等待,导致您的 shell 挂起。 exec,当没有传递任何命令时,只是将其重定向应用到当前 shell;重定向到 - 关闭 FD。我们需要使用 eval 因为 Bash 似乎在 exec ${co[1]}>&- 上有问题,将 FD 解释为命令而不是重定向的一部分;使用 eval 允许先替换该变量,然后再执行。

mapfile -tu ${co[0]} times_a

最后我们实际上从协进程中读取了标准的数据。我们已经成功地在这个 shell 中运行了 timesmapfile 命令,并且没有使用临时文件,尽管我们确实使用了一个临时进程作为两者之间的管道命令。

请注意,这有一个微妙的竞争。如果您一条一条地执行这些命令,而不是全部作为一条命令执行,那么最后一条会失败;因为当您关闭 cat 的标准时,它会退出,从而导致协进程退出并关闭 FD。看起来当全部在一行上执行时,mapfile 的执行速度足够快,以至于协进程在运行时仍然处于打开状态,因此它可以从管道中读取;但我可能会走运。我还没有找到解决这个问题的好方法。

总而言之,写出临时文件要简单得多。我会使用 mktemp 生成一个文件名,如果您在脚本中,添加一个陷阱以确保您在退出前清理您的临时文件:

tempnam=$(mktemp)
trap "rm '$tempnam'" EXIT
times > ${tempnam}
mapfile -t times_a < ${tempnam}

关于Bash:将内置的 'times' 的输出分配给变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13370318/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com