我尝试调用脚本 deepScript 并在另一个脚本 shallowScript 中处理其输出;它看起来像下面的代码:
shallowScript.sh
#!/bin/zsh
exec 1> >( tr "[a-z]" "[A-Z]" )
print "Hello - this is shallowScript"
. ./deepScript.sh
deepScript.sh
#!/bin/zsh
print "Hello - this is deepScript"
现在,当我运行 ./ shallowScript.sh 时,结果是不稳定的:要么按预期工作(很少),要么打印一个空行后跟两个预期行(有时候),或者它打印两行,然后挂起,直到我点击返回并给它换行(大部分时间)。 到目前为止,我发现了以下内容:
我浏览了很多关于进程替换和重定向的论坛和帖子,但无法找到如何保证我的脚本同步调用命令。想法?
zsh --version
zsh 5.0.5 (x86_64-apple-darwin14.0)
[编辑]
由于此策略似乎必然会失败或导致可怕的解决方法语法,因此这是另一种似乎与可承受语法一起使用的策略:我从 shallowScript.sh 中删除了所有重定向创建了第三个脚本,输出处理在函数中发生:
shallowScript.sh
#!/bin/zsh
print "Hello - this is shallowScript"
. ./deepScript.sh
thirdScript.sh
#!/bin/zsh
function _process {
while read input; do
echo $input | tr "[a-z]" "[A-Z]"
done
}
. ./shallowScript.sh | _process
答案 0 :(得分:1)
我想问题是你在执行脚本后没有看到提示符:
$ ./shallowScript.sh
$ HELLO - THIS IS SHALLOWSCRIPT
HELLO - THIS IS DEEPSCRIPT
(nothing here)
并认为它挂在这里并等待换行符。实际上它没有,行为是非常期待的。
您可以输入任何shell命令,而不是换行符,例如ls
它将被执行。
$ ./shallowScript.sh
$ HELLO - THIS IS SHALLOWSCRIPT <--- note the prompt in this line
HELLO - THIS IS DEEPSCRIPT
echo test <--- my input
test <--- its result
$
这里发生的是:第一个shell(正在运行的shallowScript.sh
)创建一个管道,执行dup2
调用以将其stdout
(fd 1)转发到写入创建管道的结尾然后分叉一个新进程(tr
),以便父进程打印到stdout
的所有内容都发送到stdin
的{{1}}。
接下来发生的是主shell(您键入初始命令tr
的那个)并不知道它应该延迟打印下一个命令提示符,直到./shallowScript.sh
进程结束。它对tr
一无所知,所以只等待tr
执行,然后打印提示。 shallowScript.sh
当时仍然在运行,这就是为什么它的输出(两行)在打印提示后出现,并且您认为shell正在等待换行。事实上,它已经为下一个命令做好了准备。您可以在脚本输出之前,之内或之后的某处看到打印的提示符(tr
字符或其他内容),这取决于$
进程完成的速度。
每次你的进程分叉时,你会看到这种行为,当父母已经死亡时,孩子继续写入tr
。
长话短说,试试这个:
stdout
这里shell会在打印下一个提示之前等待$ ./shallowScript.sh | cat
HELLO - THIS IS SHALLOWSCRIPT
HELLO - THIS IS DEEPSCRIPT
$
进程完成,cat
只有在所有输入(例如cat
的输出)都是完成时才会完成处理,就像你期望的那样。
更新:在zsh docs中找到相关引文:http://zsh.sourceforge.net/Doc/Release/Expansion.html#Process-Substitution
tr
还有一个问题;当它附加到外部命令时,父shell不会等待进程完成,因此紧接着的命令不能依赖于结果完成。问题和解决方案与重定向中的>(process)
部分中描述的相同。因此,在上面的例子的简化版本中:MULTIOS
(请注意,不涉及
paste <(cut -f1 file1) <(cut -f3 file2) > >(process)
),就父shell而言,进程将异步运行。解决方法是:MULTIOS
在你的情况下它会给出这样的东西:
{ paste <(cut -f1 file1) <(cut -f3 file2) } > >(process)
当然有效,但看起来比原版更糟糕。