在 Bash 中,如何计算和捕获管道中中间节点的结果?
例如,给定一个整数列表和一个命令或函数maximum
,使用单个 Bash 管道,如何捕获变量中整数列表的最大值,同时将该列表输出到标准输出?
在下面的 Bash 脚本中,我们的想法是更改函数,capture_maximum_and_print_numbers
使其成为单个管道。
function maximum {
awk 'NR==1||$0>x{x=$0}END{print x}'
}
function capture_maximum_and_print_numbers {
local numbers="3\n6\n1\n4\n2\n9\n5\n"
maximum=$(printf $numbers | maximum)
printf $numbers
}
capture_maximum_and_print_numbers
printf "maximum=$maximum\n"
答案1
如果您严格要求将结果分配给变量并将数字列表输出到单行中的标准输出,那么以下内容将为您提供您想要的内容(我更改了最大函数的名称以对应于它的功能,变量$maximum
对应于存储的结果本身):
function calc_max {
awk 'NR==1||$0>x{x=$0}END{print x}'
}
function capture_maximum_and_print_numbers {
local numbers="3\n6\n1\n4\n2\n9\n5\n"
export maximum=$(printf $numbers | tee /dev/tty | calc_max)
}
capture_maximum_and_print_numbers
echo max_result="$maximum"
#You have stored the max_result variable and can pass it to whatever you want.
tee
可以在长命令管道的中间使用,将“当前”结果存储在不同的文件中,输出到标准输出等。它将单个管道分成具有单独目标的多个副本,同时仍然允许您的“主”管道进一步向下处理连锁,链条。
tee dev/tty
对应于当前tty
终端的管道,/dev/tty
并将出现在每个 *nix 系统上
答案2
#!/bin/sh
generate_data () {
shuf -i 0-1000 -n 10 -r
}
print_maximum () {
awk 'NR == 1 || m < $0 { m = $0 } END { print m }'
}
exec 3>&1
maximum=$(
generate_data |
tee /dev/fd/3 |
print_maximum
)
exec 3>&-
printf 'maximum = %d\n' "$maximum"
这会传递一些随机数tee
,将它们复制到文件描述符 3 和 的标准输出tee
。标准输出由 读取print_maximum
,它查找并输出生成的数字中最大的数字。
文件描述符 3 最初作为 shell 标准输出流的副本打开(使用exec 3>&1
),这意味着当tee
写入它时(通过写入/dev/fd/3
),数据将出现在 shell 的标准输出上。该文件描述符稍后被关闭(使用exec 3>&-
)。
请注意,该脚本使用,/bin/sh
因为它不需要使用任何 bash-isms。尽管如此bash
,您可以保证它/dev/fd/3
可以用作文件描述符 3,并且不依赖于系统提供的路径。
运行示例:
$ sh script
918
787
290
998
737
1000
845
374
497
809
maximum = 1000
grep
为了表明所有输出都是在脚本的标准输出上生成的,我可以表明生成的数据是可能的:
$ sh script | grep -F 0
100
807
maximum = 807
$ sh script | grep -F 0
440
207