2016-03-26 11 views
9

Tôi đã Bash scripting trong một thời gian và tôi tự hỏi nếu có bất kỳ sự khác biệt giữa hai hình thức phủ định với lệnh test:Có sự khác biệt nào giữa việc phủ nhận trước/sau một lệnh kiểm tra không?

if [ ! condition ]; then 
fi 

if ! [ condition ]; then 
fi 

Đầu tiên nói với vỏ để vượt qua các đối số ! condition để kiểm tra , để chương trình tự chăm sóc bản thân phủ định. Mặt khác, lần thứ hai vượt qua condition để kiểm tra và cho phép trình bao tự phủ nhận mã lỗi.

Có bất kỳ cạm bẫy nào tôi cần lưu ý khi chọn giữa hai biểu mẫu này không? Giá trị nào của $condition có thể làm cho kết quả khác nhau giữa chúng?

(Tôi có vẻ nhớ đọc một bài báo cách đây một thời gian thảo luận về điều này, nhưng tôi không nhớ làm thế nào để tìm thấy nó/chính xác những gì đã được thảo luận.)

+1

Không thực sự là một điều đáng tiếc, vì thật khó để xây dựng một kịch bản thực tế nơi điều này sẽ xảy ra, nhưng hãy nhớ rằng trong '! [condition] 'the'! 'là một toán tử shell, phủ nhận trạng thái thoát của một lệnh, trong khi trong' [! condition '' '' chỉ là một đối số chuỗi cho lệnh '['. Sau 'foo ="! Bar "', so sánh '[" $ foo "]' với '[$ foo]'. – chepner

Trả lời

6

Để xây dựng trên chepner 's bình luận sâu sắc về vấn đề:

  • Trong [ ! condition ], các ! chỉ là một luận đến sốđược dựng sẵn (một bí danh hiệu dụng của nội trang test); nó sẽ xảy ra rằng đối số thông dịch/test diễn giải ! làm phủ định.

  • Trong ! [ condition ], các !một từ khóa vỏ mà phủ nhận bất cứ điều gì chỉ huy nó được theo sau bởi (mà sẽ xảy ra là [ trong trường hợp này).

Một điều mà cú pháp ! [ condition ] ngầm cung cấp cho bạn là phủ định áp dụng cho bất cứ điều gì [ condition ] đánh giá để như toàn bộ một, vì vậy nếu đó là ý định, bạn không cần phải lo lắng về việc ưu tiên điều hành.

Hiệu suất khôn ngoan, cú pháp bạn chọn có thể không tạo ra nhiều khác biệt; kiểm tra nhanh chóng gợi ý:

  • Nếu condition là theo nghĩa đen như nhau trong cả hai trường hợp, đi qua ! như một lập luận để [ là không đáng kể nhanh hơn.

  • Nếu ! được sử dụng như một từ khóa , và do đó bạn có thể đơn giản hóa điều kiện bằng cách không lo lắng về việc ưu tiên, nó có thể nhanh hơn một chút (ví dụ, ! [ 0 -o 1 ] vs [ ! \(0 -o 1 \) ]; lưu ý POSIX đặc tả không khuyến khích. sử dụng -a-o do sự mơ hồ).

Điều đó nói rằng, nếu chúng ta đang nói về Bash, sau đó bạn nên xem xét sử dụng [[ thay vì [, vì [[ là một từ khóa vỏ đó phân tích các biểu hiện kèm theo trong một đặc biệt ngữ cảnh:

  • cung cấp nhiều tính năng hơn
  • al mức thấp bạn kết hợp một cách an toàn biểu với &&||
  • đi kèm với những bất ngờ ít
  • cũng là hơi nhanh hơn (mặc dù hiếm khi sẽ quan trọng trong tu tập)

Xem this answer của tôi.

2

! phủ nhận mã lối ra của lệnh sau:

$ ! test 1 = 1 || echo $? # negate command with true expression 
1 

Như đã nói ở trang man, test (và [ dựng sẵn tương tự) thoát với trạng thái xác định bằng biểu thức sau đây:

$ test ! 1 = 1 || echo $? # return false expression 
1 
$ [ ! 1 = 1 ] || echo $? 
1 

Đối với một biểu thức đã cho:

  • trên một mặt, bạn hủy bỏ lệnh test thoát với trạng thái biểu hiện đúng.
  • ở phía bên kia, bạn phủ nhận một biểu thức và test lệnh (hoặc [) thoát với trạng thái giả của nó

Cả hai sẽ có tác dụng tương tự.

Vì vậy, tôi sẽ nói rằng các cú pháp này là tương đương. Với lợi thế cho các bài kiểm tra chất phủ bên ngoài ! cho phép:

$ ! [ 1 = 1 -a 2 = 2 ] || echo $? 
1 
+0

Bạn có thể lưu ý rằng một sự thích ứng nhỏ của ví dụ thứ ba trong tập đầu tiên cũng báo cáo '1':' test! false || echo $? '. Đó là bởi vì thử nghiệm đang kiểm tra xem chuỗi ('true' hoặc' false') có trống hay không. Tương tự với ví dụ thứ hai trong tập đầu tiên; thay thế 'true' bằng' false' không thay đổi kết quả. –

+0

Bạn nói đúng. Thay thế nó bằng những gì tôi nên là: một biểu thức. – SLePort

+0

Có lẽ bạn nên lưu ý rằng '==' hoạt động trên 'bash' nhưng không phải' dấu gạch ngang'. –

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