获取 chained/piped 命令结果到 shell 变量

Getting chained/piped commands result to shell variable

给定 db2 proc 调用的输出:

$ db2 "call SOME_PROC(103,5,0,'','',0,0)"

  Return Status = 0

我只想得到这个值,当我 'chain-em-up' 它没有像我认为的那样工作时,所以给出:

$ db2 "call SOME_PROC(103,5,0,'','',0,0)" | sed -rn 's/ *Return Status *= *([0-9]+)//p'
0

我试着把它们串起来:

$ var=$(db2 "call SOME_PROC(103,5,0,'','',0,0)" | sed -rn 's/ *Return Status *= *([0-9]+)//p')
$ echo $var

你什么也得不到!

但是如果你重定向到 tmp 文件:

$ db2 "call SOME_PROC(103,5,0,'','',0,0)" > /tmp/fff
$ var=$(cat /tmp/fff | sed -rn 's/ *Return Status *= *([0-9]+)//p')
$ echo $var
0

明白了...

同样,如果你输入 var:

$ var=$(db2 "call DB2INST1.USP_SPOTLIGHT_GET_DATA(103,5,0,'','',0,0)")
$ var=$(echo $var | sed -rn 's/ *Return Status *= *([0-9]+)//p')
$ echo $var
0

你也明白了...

有没有办法在我第一次尝试时获得价值?而且我想知道为什么它不起作用?我错过了什么?

我也尝试了下面的方法,它也没有给出任何结果!

cat <(db2 -x "call DB2INST1.USP_SPOTLIGHT_GET_DATA(103,5,0,'','',0,0)" | sed -rn 's/ *Return Status *= *([0-9]+)//p')

db2 命令行界面要求 db2 命令作为启动连接的命令的父命令的直接子命令发出。换句话说,db2 calldb2 connect 命令需要从同一个 shell 进程启动。

这与许多 shell 功能交互不佳:

  • 管道:cmd1 | cmd2 运行s 子 shells 中的两个命令(不同进程)。

  • 命令替换:$(cmd) 运行子shell中的命令。

  • 进程替换(bash):<(cmd) 运行s 子命令shell.

然而,如果 shell 是 bash,情况就不是那么受限,所以在某些情况下,上述结构仍然适用于 db2。在管道和命令替换中,如果子 shell 中的命令 运行 足够简单,bash 将优化掉子 shell。 (粗略地说,它必须是一个没有重定向的简单命令。)

因此,例如,如果某些 bash 进程 P 执行

cmd1 | cmd2

那么两个命令都有 P 作为它们的父命令,因为它们都是简单的命令。与

类似
a=$(cmd)

但是,如果流水线命令或替换命令不简单,则需要 subshell。例如,即使 { ...} 不需要 subshell,语法也不是简单的命令。所以在

{ cmd1; } | cmd2

第一个命令是子命令shell的子命令,而第二个命令是主命令shell的子命令。

特别是在

a=$(cmd1 | cmd2)

bash 不会优化命令替换子 shell,因为 cmd1 | cmd2 不是一个简单的命令。所以它会创建一个subshell来执行管道; subshell 将应用优化,因此不会有额外的 subshell 来执行简单命令 cmd1cmd2.

简而言之,您可以将 db2 call 的输出进行管道化,也可以将输出捕获到变量中,但不能将管道的输出捕获到变量中。


其他 shell 能够更多(或更少)进行 subshell 优化。例如,对于 zsh,您可以使用进程替换来避免 subshell:

# This will work with zsh but not with bash
var=$(db2 "call ..." > >(sed -rn ...))

语法cmd1 > >(cmd2)与管道cmd1 | cmd2非常相似,但不同之处在于它在语法上是一个简单的命令。对于 zsh,这足以允许消除 subshell(但对于 bash,如果命令涉及重定向,则不会优化掉 subshell)。

正如@rici 如此出色地解释了这一切,我只想现场展示它:

cmd | cmd 你得到:

$ db2 "call SOME_PROC(103,5,0,'','',0,0)" | cat

  Return Status = 0

但是 {cmd ;} | cmd 你得到:

$ { db2 "call SOME_PROC(103,5,0,'','',0,0)" ;} | cat
SQL1024N  A database connection does not exist.  SQLSTATE=08003