模仿Python“for-else”构造

问题描述 投票:15回答:6

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,但如果循环通过条件失败(对于while)或迭代结束(对于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

这更加冗长。

bash for-else
6个回答
6
投票

使用子shell:

( 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"

8
投票

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

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

7
投票

介绍类似语法的东西非常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

2
投票

你可以这样做,但我个人觉得很难读:

while :;
  do for i in x y z; do
    if [[ condition ]]; then
      # do something
      break 2
  done
  echo Nothing matched the condition
  break
done

1
投票

你可以改变这个

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

对这样简单的事情

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

如果你之后只有一个声明,虽然这并没有真正帮助太多。


1
投票

我也很喜欢devnull的答案,但这更像是pythonic:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.