我最终决定一次处理一行文件的成语是:
coproc cat auto/etc/build.cfg
while read -u ${COPROC[0]} BRANCH TARGET SVNSRC SVNTAG BUILDTYPE DISTTYPE DISTARGS
do
... commands ...
done
Run Code Online (Sandbox Code Playgroud)
我知道简单的情况cat我可以使用输入重定向.这是一个简化版本,其中真实版本使用egrep来选择行的子集.
不幸的是,这不起作用.
$ cat test.sh
coproc cat auto/etc/build.cfg
while read -u ${COPROC[0]} BRANCH TARGET SVNSRC SVNTAG BUILDTYPE DISTTYPE DISTARGS
do
echo hello
done
$ bash -x test.sh
+ read -u 63 BRANCH TARGET SVNSRC SVNTAG BUILDTYPE DISTTYPE DISTARGS
+ cat auto/etc/build.cfg
+ echo hello
hello
+ read -u BRANCH TARGET SVNSRC SVNTAG BUILDTYPE DISTTYPE DISTARGS
test.sh: line 2: read: BRANCH: invalid file descriptor specification
Run Code Online (Sandbox Code Playgroud)
看起来,即使文件中有4行,到第二次迭代时,协同处理已经消失,连同其文件描述符,并且${COPROC[*]}变量已经未设置(请注意第二次读取中缺少的fd).
更复杂的是,我在Cygwin和Linux(Fedora)中工作,这在两种环境中表现出略微不同的行为.在Linux中,我得到了上述行为.在Cygwin中,一些命令(即echo内置的bash)不会导致此问题.在这两种环境中,运行任何外部命令都会杀死协同进程并抛出其描述符.
我想这里真正的问题是:
在bash中,我该如何完成
while read (list of vars) from file
do
one or more commands
done
Run Code Online (Sandbox Code Playgroud)
配置文件很短,所以如果我必须将整个文件加载到一个数组中,那将是有效的.
我真的很惊讶这在bash中如此之难.
我不确定为什么你的使用coproc不起作用.您的示例适用于Mac OS X上的bash 4.2.8.也许某些版本的bash在这里有错误.
听起来你可以从进程替换重定向而不是使用协同进程.
while read foo bar baz quux; do
: use foo, bar, baz, quux in various commands
done < <(commands | that | generate --your lines-to-read)
Run Code Online (Sandbox Code Playgroud)
当您的输入不在可以使用普通重定向的简单文件中时,这可能很方便.
如果你想坚持下去coproc,你可能可以使用替代配方:
coproc { commands | that | generate --your lines-to-read ; }
while read foo bar baz quux; do
: use foo, bar, baz, quux in various commands
done <&${COPROC[0]}
Run Code Online (Sandbox Code Playgroud)