在bash中,如何将某些输出捕获到变量中,让其余的内容进入标准输出?

6

我知道 bash 有“捕获输出”的功能,类似于以下两个单独的文件:

sub.sh:     echo hello
main.sh:    greeting="$(./sub.sh)"

这将把变量greeting设置为hello

然而,我需要编写一个脚本,在其中只捕获一些信息,允许其余的内容转到“正常”的标准输出:

sub.sh:     xyzzy hello ; plugh goodbye
main.sh:    greeting="$(./sub.sh)"

我希望的是把代码中的 hello 放置到变量 greeting 中,但将goodbye 发送到main.sh 的标准输出。为了实现这种行为,魔术命令xyzzyplugh需要替换成什么(或者在main.sh中可以做些什么)?我猜可以通过一些巧妙的句柄重定向来实现,但我不确定。如果不可能,那我将不得不写一个临时文件,以后再使用,但我更愿意避免这样做。
为了让事情更清晰,这里是我正在使用的测试用例(目前使用的是不起作用的文件句柄3方法)。首先是sub.sh
echo xx_greeting >&3 # This should be captured to variable.
echo xx_stdout       # This should show up on stdout.
echo xx_stderr >&2   # This should show up on stderr.

接着是main.sh

greeting="$(./sub.sh)" 3>&1
echo "Greeting was ${greeting}"

我是这样运行它的:

./main.sh >/tmp/out 2>/tmp.err

期望看到以下文件:

/tmp/out:
    xx_stdout
    Greeting was xx_greeting 
/tmp/err:
    xx_stderr

当程序被执行时,每个文件描述符只指向一个位置,即使该位置是另一个执行复杂逻辑的程序的标准输入(例如读取第一行然后将其余部分转发到其他地方)。 - Charles Duffy
5
使用额外的文件描述符:sub.sh: echo hello; echo nasty >&3main.sh: exec 3>&1; var=$(./sub.sh) - user10678532
1个回答

2

可以通过引入一个额外的文件描述符来实现。首先是用于测试的sub.sh脚本,它将不同的内容写入三个不同的描述符(对于第一个隐式使用>&1):

echo for-var
echo for-out >&3
echo for-err >&2

其次,调用它的main.sh
exec 3>&1
greeting="$(./sub.sh)"
echo "Variable is ${greeting}"

然后,您只需运行它,确保知道输出将发送到不同位置:

pax> ./main.sh > xxout 2> xxerr

pax> cat xxout
for-out
Variable is for-var

pax> cat xxerr
for-err

因此,您可以看到,在从main.sh调用sub.sh时,写入文件句柄1的内容会进入捕获变量,写入文件句柄2的内容会进入标准错误输出,写入文件句柄3的内容会进入标准输出。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接