首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >bash coproc和剩余coproc输出

bash coproc和剩余coproc输出
EN

Stack Overflow用户
提问于 2011-10-04 17:48:04
回答 3查看 4.7K关注 0票数 10

我需要将一些配置数据读入bash脚本中的环境变量中。

“明显”(但不正确)的模式是:

代码语言:javascript
复制
egrep "pattern" config-file.cfg | read VAR1 VAR2 VAR3 etc...

这将失败,因为read在子shell中运行,因此不能在调用的shell中设置变量。所以我想出了一个替代方案

代码语言:javascript
复制
coproc egrep "pattern" config-file.cfg
read -u ${COPROC[0]} VAR1 VAR2 VAR3 etc...

效果很好。

为了测试如果coprocess返回多行会发生什么,我尝试了如下:

代码语言:javascript
复制
coproc cat config-file.cfg
read -u ${COPROC[0]} VAR1 VAR2 VAR3 etc...

其中config-file.cfg包含三行。

代码语言:javascript
复制
$ cat config-file.cfg
LINE1 A1 B1 C1
LINE2 A2 B2 C2
LINE3 A3 B3 C3

我希望这将处理文件中的第一行,然后是某种“断管”错误消息。当执行第一行的处理时,没有错误消息,也没有运行协进程。

于是,我在脚本中尝试了以下内容:

代码语言:javascript
复制
$ cat test.sh
coproc cat config-file.cfg
read -u ${COPROC[0]} VAR1 VAR2 VAR3 VAR4
echo $VAR1 $VAR2 $VAR3 $VAR4
wait
echo $?

运行它:

代码语言:javascript
复制
$ bash -x test.sh
+ read -u 63 VAR1 VAR2 VAR3 VAR4
+ cat config-file.cfg
LINE1 A1 B1 C1
+ wait
+ echo 0
0

剩下的两条线去哪了?我本来希望“断管”或wait挂起,因为没有什么可以读取剩下的行,但正如您所看到的,返回代码为零。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-10-04 20:20:57

根据上面的注释,您可以使用过程替代来实现这一点。这样,read不会在子shell中运行,捕获的vars将在当前shell中可用。

代码语言:javascript
复制
read VAR1 VAR2 VAR3 < <(egrep "pattern" config-file.cfg)

“如果使用<(列表)表单,则应读取作为参数传递的文件以获得列表的输出”--他们指的是什么“传递为agrument的文件”?

这对我来说也很神秘。高级Bash脚本指南中的关于过程替代的一章有一个更全面的解释。

在我看来,当使用<(cmd)语法时,cmd的输出通过指定的管道(或临时文件)可用,语法被管道/文件的文件名所取代。因此,对于上面的例子,它最终将等价于:

代码语言:javascript
复制
read VAR1 VAR2 VAR3 < /dev/fd/63

其中/dev/fd/63是连接到cmd标准输出的命名管道。

票数 6
EN

Stack Overflow用户

发布于 2011-10-04 18:41:21

如果我正确理解了你的问题(希望我没有说出显而易见的问题),请一次读一行,如下所示:

代码语言:javascript
复制
$ read a b c < config-file.cfg && echo $?
0

或者:

代码语言:javascript
复制
$ printf '%s\n%s\n' one two | { read; echo "$REPLY";}
one

$ echo ${PIPESTATUS[@]}
0 0

要读取所有输入,您需要一个循环:

代码语言:javascript
复制
$ coproc cat config-file.cfg
[1] 3460

$ while read -u ${COPROC[0]} VAR1 VAR2 VAR3; do echo $VAR1 $VAR2 $VAR3; done
LINE1 A1 B1 C1
LINE2 A2 B2 C2
LINE3 A3 B3 C3
[1]+  Done                    coproc COPROC cat config-file.cfg

补充一下,这一点在常见问题中已经解释过了。

票数 2
EN

Stack Overflow用户

发布于 2019-03-09 12:59:02

所发生的情况是,一旦子shell完成,父shell将清理并关闭FDs。你真幸运,你甚至能读到第一行!

在一个交互的shell中尝试这样做:

代码语言:javascript
复制
$ coproc ECHO { echo foo; echo bar; }
[2] 16472
[2]+  Done                    coproc ECHO { echo foo; echo bar; }
$ read -u ${ECHO[0]}; echo $REPLY
bash: read: -u: option requires an argument
read: usage: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]

它甚至清除了环境变量。

现在试试这个:

代码语言:javascript
复制
$ coproc ECHO { echo foo; echo bar; sleep 30; }
[2] 16485
$ read -u ${ECHO[0]}; echo $REPLY
foo
$ read -u ${ECHO[0]}; echo $REPLY
bar
$ read -u ${ECHO[0]}; echo $REPLY # blocks until the 30 seconds are up

[2]+  Done                    coproc ECHO { echo foo; echo bar; sleep 30; }

至于解决问题背后的问题:是的,重定向和过程替换是给出的具体例子的更好的选择。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7651946

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档