如果输入由内部“while read”处理,我怎么能打破shell脚本循环?

时间:2013-06-06 04:07:01

标签: bash shell unix

这是一个shell脚本。请将受控环境随机数生成子shell推断为在异步日志记录情况下使用它(我打算将它用于inotifywait输出)。

group=0
(
  for val in {1..10}; do 
    echo "$RANDOM/20000" | bc | xargs sleep # this waits 0, 1, or 2 seconds before each number is printed
    echo $val 
  done 
) | while true; do 
      while read -t 1 line; do 
        echo "read time=$group read=$line" 
      done
      ((group++))
    done

这会产生如下输出:

read time=1 read=1
read time=2 read=2
read time=2 read=3
read time=3 read=4
read time=3 read=5
read time=3 read=6
read time=4 read=7
read time=5 read=8
read time=5 read=9
read time=5 read=10

但它会挂起并且不会退出。它卡在外循环中,不断递增group

$ echo $group 
1336794

显然,由于输入已完成,内循环已退出,变量的增量进入超级驱动。

如何退出循环?有没有类似else的某种类型的break子句,一旦输入完成后,我就可以破解内部for循环以便{{1}}退出外部循环?

当然,必须有一个更强大的方法,而不是在外循环中进行计时,看它是否过快。

3 个答案:

答案 0 :(得分:3)

#!/bin/bash
mkfifo outputs
for val in {1..10}; do
    echo "$RANDOM/20000" | bc | xargs sleep
    echo $val 
done > outputs &
group=0
time=$(date +%s%N)
while read line; do
    ctime=$(date +%s%N)
    [ $(( $ctime - $time )) -gt 1000000000 ] && let group++
    echo "read time=$group read=$line"
    time=$ctime
done < outputs

答案 1 :(得分:1)

这是基于读取返回码的另一种解决方案。根据bash文档,当read -t退出超时时,它的返回码大于128,因此您可以区分EOF和超时。

function random_timed_output
{
  for val in {1..10}; do
    sleep $(( $RANDOM/20000 ))
    echo $val 
  done
}

group=0
random_timed_output | while true; do
  read -t 1 line
  rc=$?
  if [ $rc -gt 128 ]; then
    #read exit for timeout
    ((group++))
  elif [ $rc -gt 0 ]; then
    #read exit for error or EOF
    break
  else
    #read exit OK
    echo "read time=$group read=$line" 
  fi
done

答案 2 :(得分:0)

 Kaizen ~/so_test $ cat zcntr.sh
 ilimit=10; ## the length of list in for loop ... 

grp=0
(   for val in {1..10}; do
     #echo "$RANDOM/10000" | bc | xargs sleep
     sleep $(($RANDOM/10000));
     echo $val
     done
 ) | while true; do

  while read -t 1 line; do
    echo "read time=$grp read=$line"
  done

  ((grp++));

  if [ $grp -eq $ilimit ]
     then
       break ;
  fi

done

输出效果不理想,但我稍后会看一下:

Kaizen ~/so_test $ ./zcntr.sh
  read time=0 read=1
  read time=0 read=2
  read time=1 read=
  read time=1 read=4
  read time=1 read=5
  ./zcntr.sh: line 13: read: read error: 0: Permission denied
  read time=4 read=7
  read time=6 read=
  read time=7 read=
  read time=7 read=10

无论如何都有帮助吗?