Подражание конструкции "for-else" Python

У 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

который является более подробным.

Ответ 1

Используя подоболочку:

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

Ответ 2

В список циклов можно указать значение часового:

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

Ответ 3

Что-то очень взломанное, чтобы ввести аналогичный синтаксис:

#!/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

Ответ 4

Вы можете это сделать, но мне лично трудно читать:

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

Ответ 5

Вы можете изменить этот

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

для чего-то более простого, подобного этому

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

если после этого у вас есть только одно утверждение, хотя это не очень поможет.

Ответ 6

Мне также нравится devnull ответ, но это еще более pythonic:

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

Это будет только эхо "ничего не согласовано", если цикл не сломался.