我需要将一些配置数据读入bash脚本中的环境变量中。
“明显”(但不正确)的模式是:
egrep "pattern" config-file.cfg | read VAR1 VAR2 VAR3 etc...这将失败,因为read在子shell中运行,因此不能在调用的shell中设置变量。所以我想出了一个替代方案
coproc egrep "pattern" config-file.cfg
read -u ${COPROC[0]} VAR1 VAR2 VAR3 etc...效果很好。
为了测试如果coprocess返回多行会发生什么,我尝试了如下:
coproc cat config-file.cfg
read -u ${COPROC[0]} VAR1 VAR2 VAR3 etc...其中config-file.cfg包含三行。
$ cat config-file.cfg
LINE1 A1 B1 C1
LINE2 A2 B2 C2
LINE3 A3 B3 C3我希望这将处理文件中的第一行,然后是某种“断管”错误消息。当执行第一行的处理时,没有错误消息,也没有运行协进程。
于是,我在脚本中尝试了以下内容:
$ cat test.sh
coproc cat config-file.cfg
read -u ${COPROC[0]} VAR1 VAR2 VAR3 VAR4
echo $VAR1 $VAR2 $VAR3 $VAR4
wait
echo $?运行它:
$ bash -x test.sh
+ read -u 63 VAR1 VAR2 VAR3 VAR4
+ cat config-file.cfg
LINE1 A1 B1 C1
+ wait
+ echo 0
0剩下的两条线去哪了?我本来希望“断管”或wait挂起,因为没有什么可以读取剩下的行,但正如您所看到的,返回代码为零。
发布于 2011-10-04 20:20:57
根据上面的注释,您可以使用过程替代来实现这一点。这样,read不会在子shell中运行,捕获的vars将在当前shell中可用。
read VAR1 VAR2 VAR3 < <(egrep "pattern" config-file.cfg)“如果使用<(列表)表单,则应读取作为参数传递的文件以获得列表的输出”--他们指的是什么“传递为agrument的文件”?
这对我来说也很神秘。高级Bash脚本指南中的关于过程替代的一章有一个更全面的解释。
在我看来,当使用<(cmd)语法时,cmd的输出通过指定的管道(或临时文件)可用,语法被管道/文件的文件名所取代。因此,对于上面的例子,它最终将等价于:
read VAR1 VAR2 VAR3 < /dev/fd/63其中/dev/fd/63是连接到cmd标准输出的命名管道。
发布于 2011-10-04 18:41:21
如果我正确理解了你的问题(希望我没有说出显而易见的问题),请一次读一行,如下所示:
$ read a b c < config-file.cfg && echo $?
0或者:
$ printf '%s\n%s\n' one two | { read; echo "$REPLY";}
one
$ echo ${PIPESTATUS[@]}
0 0要读取所有输入,您需要一个循环:
$ 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补充一下,这一点在常见问题中已经解释过了。
发布于 2019-03-09 12:59:02
所发生的情况是,一旦子shell完成,父shell将清理并关闭FDs。你真幸运,你甚至能读到第一行!
在一个交互的shell中尝试这样做:
$ 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 ...]它甚至清除了环境变量。
现在试试这个:
$ 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; }至于解决问题背后的问题:是的,重定向和过程替换是给出的具体例子的更好的选择。
https://stackoverflow.com/questions/7651946
复制相似问题