我对ksh有一个问题,因为while循环无法遵守"while"条件。我现在应该补充一点,这是我的客户机Solaris机箱上的ksh88。(这是一个单独的问题,在这个论坛上无法解决。;)我看到了Lance的问题和一些类似的问题,但我发现没有一个能解决这个问题。(免责声明:不,我没有看过这个论坛上的每一个ksh问题)
下面是一段非常精简的代码,它复制了这个问题:
1 #!/usr/bin/ksh
2 #
3 go=1
4 set -x
5 tail -0f loop-test.txt | while [[ $go -eq 1 ]]
6 do
7 read lbuff
8 set $lbuff
9 nwords=$#
10 printf "Line has %d words <%s>n" $nwords "${lbuff}"
11 if [[ "${lbuff}" = "0" ]]
12 then
13 printf "Line consists of %s; time to absquatulaten" $lbuff
14 go=0 # Violate the WHILE condition to get out of loop
15 fi
16 done
17 printf "nLooks like I've fallen out of the loopn"
18 exit 0
我测试的方法是:
- 在后台模式下运行loop-test.sh
- 在另一个窗口中,我运行命令,如"echo some barries>>loop_test.txt"(当然没有引号)
- 当我想退出时,我键入"echo 0>>loop test.txt"
会发生什么?它确实设置go=0并显示行:
行由0组成;吸收的时间
但是不退出循环。为了突破,我在txt文件中多加了一行。循环不处理该行,只是退出循环,在退出之前发出"退出"消息。
这是怎么回事?我不想使用"break",因为在实际的脚本中,循环监视数据库引擎的日志,当它看到引擎关闭的消息时,就会设置标志。实际的脚本在退出之前仍必须处理最后几行。
对想法持开放态度,有人吗?
非常感谢!
--J.
好吧,很快就失败了。在阅读了其他几篇帖子后,我发现了一个由dogbane给出的答案,它避开了我的整个计划。他的是(2013年)一个问题的第二个答案,我看到neeraj使用的是我正在使用的相同方案。
怎么了?到while的管道一直用于将要结束的输入,例如输出端不同的文件或命令。但是,从tail
命令来看,没有明显的EOF。因此,while-in-a-subshell不知道何时终止。
多班恩的解决方案:不要使用管道。将他的逻辑应用于我的情况,基本循环是:
while read line
do
# put loop body here
done < <(tail -0f ${logfile})
没有潜艇,没问题。
关于该语法的注意事项:两者之间必须有一个空格<运营商;否则,它看起来像一个语法不好的HEREIS文档。
呃,还有一个问题:语法在ksh中不起作用,甚至在模仿ksh93的mksh(在cygwin下)中也不起作用。但它在bash中确实起到了的作用。所以我的老板会嘲笑我的,因为他知道我不喜欢bash。
所以非常感谢,dogbane。
--J
在阐明问题并解决问题后,我想到了所描述行为的原因:在设置go=0
后,循环的控制流仍然依赖于通过该管道从STDIN传入的另一行数据。
现在我已经意识到了奇怪的原因,我可以从流中推测另一种阅读方式。目前,我正在考虑以下解决方案:
- 以STDIN打开输入文件(需要研究exec语法)
- 当条件发生时,关闭STDIN(同样,需要研究语法)
然后,在循环的顶部使用更直观的while read lbuff
应该是安全的。
我今天会测试一下并公布结果。我希望其他人能从这种方法中受益(如果有效的话)。