获取 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 call
和 db2 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 来执行简单命令 cmd1
和 cmd2
.
简而言之,您可以将 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
给定 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 call
和 db2 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 来执行简单命令 cmd1
和 cmd2
.
简而言之,您可以将 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