2013-08-27 20 views
11

Python có một tính năng ngôn ngữ tiện dụng được gọi là "cho-else" (tương tự "trong khi-else"), mà trông như thế này:Bắt chước các Python "cho-else" xây dựng

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" 

Về cơ bản, else bị bỏ qua nếu ngắt vòng lặp, nhưng chạy nếu vòng lặp đã thoát qua lỗi điều kiện (đối với while) hoặc kết thúc phép lặp (đối với for).

Có cách nào để thực hiện việc này trong bash không? Điều gần nhất tôi có thể nghĩ đến là sử dụng biến cờ:

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 

có chiều dài hơn.

Trả lời

4

Sử dụng một subshell:

(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

Ngắn và ngọt. Tôi thích nó. – nneonneo

+2

Big BUG! Danh sách 'x y z' không bao giờ được đưa vào' y z' nếu 'x' là sai! @ nneonneo làm thế nào bạn có thể chấp nhận điều đó ?! –

+1

Đây là những gì tôi đang sử dụng: '(cho i in x y z; làm [điều kiện $ i] && echo" Điều kiện $ i đúng "& & exit; được thực hiện) && echo" Tìm thấy kết quả phù hợp "|| echo "Không tìm thấy kết quả phù hợp". Lưu ý việc sử dụng '&& thoát' thay vì' || exit', đó là chìa khóa để làm cho nó tiếp tục khi 'x' là sai. – nneonneo

7

Bạn có thể đặt một giá trị trọng điểm trong danh sách vòng lặp:

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

cái gì đó rất hacky để giới thiệu cú pháp tương tự:

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

Tuyệt. Bí danh đôi khi có thể hữu ích. – konsolebox

+1

@ konsolebox Tôi đồng ý, bí danh bị đánh giá thấp. Mặc dù họ là chính họ giới hạn họ giúp làm việc xung quanh những hạn chế khác, nơi họ là giải pháp duy nhất (hoặc đẹp nhất). Tôi đã sử dụng kỹ thuật này trước khi thực hiện xử lý ngoại lệ vỏ và trong khi tôi chắc chắn nhiều người tìm thấy điều này xấu xí và ngu ngốc tôi nghĩ rằng nó khá đẹp trong một cách. –

+1

Nó thực sự là một sử dụng thú vị của bí danh. Cảm ơn bạn về giải pháp (+1). – nneonneo

2

Bạn có thể làm điều này nhưng tôi cá nhân thấy khó đọc:

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

Bạn có thể thay đổi điều này

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

một cái gì đó đơn giản như thế này

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

nếu bạn chỉ có một tuyên bố sau đó, mặc dù đó là không thực sự giúp ích nhiều.

0

Tôi cũng thích câu trả lời của devnull, nhưng điều này thậm chí còn pythonic hơn:

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

này sẽ chỉ echo "không có gì phù hợp" nếu vòng lặp không phá vỡ.

Các vấn đề liên quan