Bash có điều kiện: làm thế nào để biểu thức của người Viking và người Do Thái? (nếu [! -z $ VAR && -e $ VAR])


281

Tôi đoán tôi không rõ về cách làm bài kiểm tra "và". Tôi muốn chắc chắn rằng một đối số tồn tại đang hoạt động tốt [ -e $VAR ], nhưng hóa ra điều đó cũng được đánh giá là đúng trên một chuỗi rỗng; điều mà tôi không muốn

Làm thế nào để tôi 'và' họ cùng nhau? Hoặc có một bài kiểm tra đơn phương khác hoàn thành những gì tôi muốn?

Câu trả lời:


532
if [ ! -z "$var" ] && [ -e "$var" ]; then
      # something ...
fi

9
Giải pháp này hoạt động ngay cả trong các vỏ tuân thủ nghiêm ngặt POSIX và do đó cũng trong bash; tuy nhiên, để tận dụng tối đa "bashism", hãy xem câu trả lời của @ paxdiablo.
mkuity0

2
Rất vui mừng khi thấy điều này khuyên thay vì lỗi thời -a.
Charles Duffy

1
Tôi tìm thấy một lời giải thích tuyệt vời và chi tiết khác - stackoverflow.com/questions/3601515/ từ
valentt

70

Từ bashtrang hướng dẫn:

[[ expression ]] - trả về trạng thái 0 hoặc 1 tùy theo đánh giá biểu thức biểu thức điều kiện.

Và, đối với các biểu thức, một trong các tùy chọn là:

expression1 && expression2- đúng nếu cả hai expression1expression2đều đúng.

Vì vậy, bạn có thể andkết hợp chúng lại như sau ( -nngược lại -zđể chúng ta có thể thoát khỏi !):

if [[ -n "$var" && -e "$var" ]] ; then
    echo "'$var' is non-empty and the file exists"
fi

Tuy nhiên, tôi không nghĩ rằng nó cần thiết trong trường hợp này, -e xyzzylà đúng nếu xyzzy tệp tồn tại và có thể dễ dàng xử lý các chuỗi trống. Nếu đó là những gì bạn muốn thì bạn thực sự không cần -zkiểm tra không trống:

pax> VAR=xyzzy
pax> if [[ -e $VAR ]] ; then echo yes ; fi
pax> VAR=/tmp
pax> if [[ -e $VAR ]] ; then echo yes ; fi
yes

Nói cách khác, chỉ cần sử dụng:

if [[ -e "$var" ]] ; then
    echo "'$var' exists"
fi

1
Chúng ta có thể rút ngắn nó với[[ -e "$var" ]] && echo "'$var' exists"
jaypal singh

1
Có, nếu đó là một lớp lót (như ví dụ của tôi là). Tôi sẽ không làm điều đó nếu khối điều kiện phức tạp hơn nhiều.
paxdiablo

trong trường hợp chỉ có một - thậm chí có thể là một lệnh dài, thì nên sử dụng hình thức này vì nó ngắn hơn
avp

9
if [ -n "$var" -a -e "$var" ]; then
    do something ...
fi

 


10
POSIXkhông xác định hành vi của [các bộ kiểm tra phức tạp, chúng tôi nên tránh sử dụng -ahoặc -ovới [. Tôi đọc nó ở đây .
jaypal singh

2
@ jaypal-singh Bạn nói đúng, nhưng chủ đề có bashthẻ và không đề cập đến POSIX, vì vậy tôi đăng phiên bản này hoạt động theo bashvà một số vỏ hiện đại khác.
Slava Semushin

2
Nếu bạn đang giả định việc sử dụng bashhoặc các loại đạn hiện đại khác, thậm chí còn ít lý do để đề xuất -a.
chepner

Ngay cả với bash, cách các bài kiểm tra này hoạt động không được xác định rõ trong tất cả các trường hợp góc. Cân nhắc [ "$var1" -o "$var2" ]; nếu var1=(var2=), thì những gì chúng ta có là một thử nghiệm cho dù -okhông trống, hơn là một trong hai var1hoặc var2không trống. Kiểu mơ hồ này là lý do chính đáng duy nhất cho x$varthành ngữ trong các lệnh hiện đại (nghĩa là sau những năm 90) testvới trích dẫn chính xác, và thành ngữ đó cần phải chết trong lửa.
Charles Duffy

4

Đơn giản chỉ cần trích dẫn biến của bạn:

[ -e "$VAR" ]

Điều này đánh giá [ -e "" ]nếu $VARtrống.

Phiên bản của bạn không hoạt động vì nó đánh giá [ -e ]. Bây giờ trong trường hợp này, bash chỉ cần kiểm tra xem đối số đơn ( -e) có phải là một chuỗi không trống không.

Từ trang hướng dẫn:

kiểm tra và [đánh giá các biểu thức điều kiện bằng cách sử dụng một bộ quy tắc dựa trên số lượng đối số. ...

1 đối số

Biểu thức là đúng khi và chỉ khi đối số không phải là null.

(Ngoài ra, giải pháp này có thêm lợi ích khi làm việc với tên tệp chứa dấu cách)


1

Tôi tìm thấy một câu trả lời ngay bây giờ. Cảm ơn lời đề nghị của bạn!

for e in ./*.cutoff.txt; do
if grep -q -E 'COX1|Cu-oxidase' $e
then
    echo xyz >$e.match.txt
else
    echo
fi

if grep -q -E 'AMO' $e
then
    echo abc >$e.match.txt
else
    echo
fi; done

Bất kỳ ý kiến ​​về điều đó? Có vẻ như không hiệu quả để grep hai lần, nhưng nó hoạt động ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.