在管道到的while read循环中忽略了Bash continue[n].for循环的行为符合预期



在我正在编写的脚本中,我试图退出第二个嵌套while循环,continue语句似乎被简单地忽略了,我不确定确切的原因。

来自手册:

continue [n]:
Resume  the  next  iteration of the enclosing for, while, until, or select loop.  If n is specified,
resume at the nth enclosing loop.  n must be ≥ 1.  If n is greater  than  the  number  of  enclosing
loops,  the last enclosing loop (the ``top-level'' loop) is resumed.  The return value is 0 unless n
is not greater than or equal to 1.

举例说明我的问题(ex1.sh(:

#!/bin/bash
printf "%dn" {1..3} | while read i; do
printf "%dn" {1..3} | while read j; do
sum=$(expr $i + $j)
echo "$i + $j = $sum"
[ $sum -ge 5 ] && echo continue && continue 2
done
echo 'should only see this for first cycle of i (2+3 >= 5)'
done

ex1.sh:输出

1 + 1 = 2
1 + 2 = 3
1 + 3 = 4
should only see this for first cycle of i (2+3 >= 5)
2 + 1 = 3
2 + 2 = 4
2 + 3 = 5
continue
should only see this for first cycle of i (2+3 >= 5)
3 + 1 = 4
3 + 2 = 5
continue
3 + 3 = 6
continue
should only see this for first cycle of i (2+3 >= 5)

为什么continue 2被忽略?它清楚地回响出";"继续";,并且通过使用set -x运行跟踪来确认继续运行的事实

printf的使用显然是愚蠢的ex1.sh,但它再现了我在while read x...循环中继续工作的问题。

A for循环按预期工作(ex2.sh(:

#!/bin/bash
for i in {1..3}; do
for j in {1..3}; do
sum=$(expr $i + $j)
echo "$i + $j = $sum"
[ $sum -ge 5 ] && echo continue && continue 2
done
echo 'should only see this for first cycle of i (2+3 >= 5)'
done

ex2.sh:的输出

1 + 1 = 2
1 + 2 = 3
1 + 3 = 4
should only see this for first cycle of i (2+3 >= 5)
2 + 1 = 3
2 + 2 = 4
2 + 3 = 5
continue
3 + 1 = 4
3 + 2 = 5
continue

那么,为什么ex1.sh似乎忽略了continue 2内置,而ex2.sh的行为却如预期的那样呢?

修正了我自己感谢M.Nejat Aydin的第一个例子:

#!/bin/bash
while read i; do
while read j; do
sum=$(expr $i + $j)
echo "$i + $j = $sum"
[ $sum -ge 5 ] && echo continue && continue 2
done < <(printf "%dn" {1..3})
echo 'should only see this for first cycle of i (2+3 >= 5)'
done < <(printf "%dn" {1..3})

问题是管道创建了子shell,所以我的continue语句按照手册的预期运行,在子shell知道的最外层循环处继续。

您的while循环没有嵌套。它们在不同的潜艇里运行。continue无法从父shell继续。管道(|(创建一个子shell。另一方面,由于两个while都在同一个shell中运行,因此下面的版本应该可以正常工作:

while read i; do
while read j; do
sum=$(expr $i + $j)
echo "$i + $j = $sum"
[ $sum -ge 5 ] && echo continue && continue 2
done < <(printf "%dn" {1..3})
echo 'should only see this for first cycle of i (2+3 >= 5)'
done < <(printf "%dn" {1..3})

最新更新