18

Python 有一个方便的语言特性,叫做“for-else”(类似地,“while-else”),它看起来像这样:

for obj in my_list:
    if obj == target:
        break
else: # note: this else is attached to the for, not the if
    print "nothing matched", target, "in the list"

本质上,else如果循环中断,则跳过,但如果循环通过条件失败(for while)或迭代结束(for)退出,则运行for

有没有办法做到这一点bash?我能想到的最接近的是使用标志变量:

flag=false
for i in x y z; do
    if [ condition $i ]; then
        flag=true
        break
    fi
done
if ! $flag; then
    echo "nothing in the list fulfilled the condition"
fi

这更冗长。

4

6 回答 6

9

使用子外壳:

( for i in x y z; do
    [ condition $i ] && echo "Condition $i true" && exit;
done ) && echo "Found a match" || echo "Didn't find a match"
于 2013-08-27T14:38:51.590 回答
9

您可以在循环列表中放置一个标记值:

for i in x y z 'end-of-loop'; do
    if [ condition $i ]; then
        # loop code goes here
        break
    fi
    if [ $i == 'end-of-loop' ]; then
        # your else code goes here
    fi
done
于 2013-08-27T14:19:56.243 回答
8

引入类似语法的东西非常hacky:

#!/bin/bash

shopt -s expand_aliases

alias for='_broken=0; for'
alias break='{ _broken=1; break; }'
alias forelse='done; while ((_broken==0)); do _broken=1;'

for x in a b c; do
        [ "$x" = "$1" ] && break
forelse
        echo "nothing matched"
done

 

$ ./t.sh a
$ ./t.sh d
nothing matched
于 2013-08-27T14:29:55.423 回答
3

You can do this but I personally find it hard to read:

while :;
  do for i in x y z; do
    if [[ condition ]]; then
      # do something
      break 2
  done
  echo Nothing matched the condition
  break
done
于 2013-08-27T14:31:50.260 回答
1

你可以改变这个

if ! $flag; then
    echo "nothing in the list fulfilled the condition"
fi

像这样更简单的东西

"$flag" || echo "nothing in the list fulfilled the condition"

如果您在它之后只有一个声明,尽管这并没有太大帮助。

于 2013-08-27T15:17:52.797 回答
1

我也很喜欢 devnull 的回答,但这更像是 Pythonic:

for i in x y z; do
  [ condition $i ] && break #and do stuff prior to break maybe?
done || echo "nothing matched"

如果循环没有中断,这只会回显“没有匹配”。

于 2017-03-15T07:17:09.263 回答