2013-08-27 10 views
11

Python eine praktische Sprache-Funktion "für-else" (ähnlich "während-else") genannt hat, die wie folgt aussieht:Imitieren von den Python "für-else" konstruieren

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" 

Wesentlichen die else wird übersprungen, wenn die Schleife unterbrochen wird, wird aber ausgeführt, wenn die Schleife über einen Bedingungsfehler (für while) oder das Ende der Iteration (für for) beendet wurde.

Gibt es eine Möglichkeit, dies in bash zu tun? Der nächstgelegene ich denken kann, ist eine Flag-Variable zu verwenden:

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 

die eher ausführlicher ist.

Antwort

4

eine Subshell verwenden:

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

Kurz und gut. Ich mag das. – nneonneo

+2

Großer Fehler! Die Liste von 'x y z' wird niemals zu 'y z' wenn' x' falsch ist! @nneonneo wie kannst du das akzeptieren ?! –

+1

Hier ist, was ich verwende: '(für i in x y z; tun [Zustand $ i] & & echo" Bedingung $ i wahr "& & exit; getan) && echo" Eine Übereinstimmung gefunden "|| echo "Habe keine Übereinstimmung gefunden" '. Beachten Sie die Verwendung von '&& exit' anstelle von' || exit', was der Schlüssel ist, um es fortzusetzen, wenn "x" falsch ist. – nneonneo

7

Sie einen Sentinel-Wert in der Schleife Liste setzen könnte:

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 
6

Etwas sehr hacky ähnliche Syntax vorstellen:

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

Kühl. Aliase können manchmal hilfreich sein. – konsolebox

+1

@konsolebox Ich stimme zu, Aliase sind weit unterbewertet. Obwohl sie selbst begrenzt sind, helfen sie, andere Einschränkungen zu umgehen, wo sie die einzige (oder schönste) Lösung darstellen. Ich habe diese Technik schon früher benutzt, um Shell Exception Handling zu implementieren, und obwohl ich sicher bin, dass viele Leute dieses hässliche und idiotische finden, finde ich es in gewisser Weise ziemlich schön. –

+1

Es ist eigentlich eine interessante Verwendung von Aliasen. Danke für die Lösung (+1). – nneonneo

2

Sie können dies tun, aber ich persönlich finde es schwer zu lesen:

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

Sie können diese

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

etwas einfacher wie diese

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

, wenn Sie erst nach einer Erklärung haben, obwohl das wird nicht wirklich viel helfen.

0

ich auch devnull Antwort, genießen, aber das ist noch pythonic:

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

Dies wird nur „nichts abgestimmt“ Echo, wenn die Schleife nicht brechen.

Verwandte Themen