3

这是一个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子句可以破解内部 for 循环以break跳出外部循环?

当然,必须有一种比在外循环中进行计时更稳健的方法来查看它是否通过得太快。

4

3 回答 3

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
于 2013-06-06T04:18:29.557 回答
1

这是基于读取返回码的另一种解决方案。根据read -t超时退出时的 bash 文档,它的返回码大于 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
于 2013-06-06T10:27:29.807 回答
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

这有帮助吗?

于 2013-06-06T04:40:28.677 回答