Làm thế nào để kiểm tra xem $ 1 và $ 2 có null không?


40

Tôi đang chạy một số tập lệnh vượt qua đối số chuỗi và tôi muốn làm nếu câu lệnh khác được hiển thị như bên dưới:

if [ $1 != '' ] && [ $2 != '' ]
then 
    do something.....

nhưng nó thể hiện Error too many argument. Tại sao?


Bạn nên cung cấp 1. lệnh mà bạn gọi tập lệnh và 2. đầu ra đầy đủ.
Lucio

2
Bạn nên sử dụng [[ ]]. Nếu không, bạn phải trích dẫn các biến của bạn.
Barshe De Troyer

Nếu $ 1 không tồn tại thì $ 2 sẽ trở thành $ 1, điều đó làm cho bài kiểm tra $ 1 và $ 2 đều không có vẻ liên quan.
WinEunuuchs2Unix

@ WinEunuuchs2Unix Không nhất thiết là không liên quan - trong một số trường hợp bạn muốn đảm bảo thực sự có một cái gì đó thay vì chuỗi trống hoặc null trong các đối số. $1có thể không được đặt hoặc được đặt thành chuỗi null bởi người dùng tập lệnh. Xem xét chuỗi lệnh này: $ set '' barsau đó echo "x${1}x";Cả hai biến được đặt, nhưng một trong số chúng là null.
Sergiy Kolodyazhnyy

Câu trả lời:


55

Hãy thử sử dụng thử nghiệm -z:

if [ -z "$1" ] && [ -z "$2" ]

Từ người đàn ông bash:

-z string
   True if the length of string is zero.

Nó làm việc cho tôi!
chim cánh cụt

thật thú vị khi câu trả lời được bình chọn và chấp nhận nhiều nhất không thực sự trả lời câu hỏi được hỏi.
mehmet

Khi viết tập lệnh shell di động, cờ này nên được sử dụng cẩn thận, vì trên một số Unix thương mại nhất định, cờ này bị lỗi. Xem câu trả lời của tôi cho các nguồn liên kết.
Sergiy Kolodyazhnyy

14

Vì điều này được gắn thẻ bash, tôi khuyên người ta nên sử dụng cấu trúc thử nghiệm mở rộng ( [[...]]) và quên dấu ngoặc kép:

if [[ -z $1 && -z $2 ]]; then
...

Trừ khi bạn định shtương thích / POSIX, không có lý do gì để không sử dụng [[ ]].


3

Sau đây cũng hoạt động,

if [ "$1" == "" && "$2" == ""]; then
    echo NULL
fi

Các &&dấu tách lệnh logic và khác không được phép trong cổ điển test. Bạn phải sử dụng các cấu trúc thử nghiệm khác thay thế (như -a, tôi nghĩ vậy)
muru

3

Đối với phiên bản cũ của câu trả lời, xem phần thứ hai của câu trả lời này. Nếu bạn muốn biết về chi tiết, hãy đọc tiếp

Nguyên nhân của vấn đề

Trong chính câu hỏi, có thông tin rằng OP thấy too many arguments error, khi được thử nghiệm bashdường như không phải là trường hợp:

$ [ $1 != '' ] && [ $2 != '' ]
bash: [: !=: unary operator expected

Với Ubuntu /bin/shthực sự được liên kết /bin/dashvới nhau, lỗi được báo cáo như sau:

$ sh
$ [ $1 != '' ] && [ $2 != '' ]
sh: 1: [: !=: unexpected operator

Và độc lập /bin/testcũng:

$ /usr/bin/test $1 != ''  
/usr/bin/test: missing argument after ‘’

Sidenote: Nếu bạn đang tự hỏi đó là gì /usr/bin/testvà tại sao tôi lại sử dụng bashsh, thì bạn nên biết đó [là bí danh cho testlệnh, cũng tồn tại dưới dạng thực thi độc lập hoặc phổ biến hơn - như là shell được tích hợp, thứ mà mỗi shell sẽ sử dụng trước . Đối với các ifcâu lệnh, chúng hoạt động trên các tượng thoát lệnh, do đó tại sao [testlà các lệnh, với mọi thứ khác là đối số của lệnh đó - thứ tự không đúng của các đối số dòng lệnh đó dẫn đến lỗi.

Quay lại chủ đề: không rõ làm thế nào OP có lỗi không liên quan. Tuy nhiên, trong cả 3 trường hợp, vấn đề là như nhau - biến unset sẽ được coi là rỗng, do đó, cái mà shell nhìn thấy với các biến không được trích dẫn này là

[ != '' ]

mà phá vỡ cú pháp mà testhiểu. Hãy nhớ những gì tôi đã nói về thứ tự không đúng của các đối số dòng lệnh? Do đó tại sao trích dẫn là quan trọng. Hãy bật đầu ra chẩn đoán và xem shell nào thực thi:

$ set -x
# throws error
$ [ $1 != '' ] && [ $2 != '' ] 
+ '[' '!=' '' ']'
bash: [: !=: unary operator expected
# no error
$ [ "$1" != '' ] && [ "$2" != '' ] || echo null vars
+ '[' '' '!=' '' ']'
+ echo null vars
null vars

Cách tốt hơn để kiểm tra các biến unset

Một cách tiếp cận rất thường xuyên mà bạn thấy xung quanh là:

 if [ "x$var1" == "x"  ] && [ "x$var2" == "x"  ];                                                                
 then
     echo "both variables are null"
 fi

Để trích dẫn Gilles :

Trong ["x $ 1" = "x"], tiền tố x đảm bảo rằng x "$ 1" có thể trông giống như một toán tử, và vì vậy cách duy nhất mà shell có thể phân tích kiểm tra này là bằng cách xử lý = như một toán tử nhị phân.

Có lẽ, điều này sẽ khá di động vì tôi đã thấy những điều này trong /bin/shcác kịch bản. Nó cũng có thể được kết hợp như trong

if [ "x${var1}${var2}" == "x" ]; then
    ...
fi

Tất nhiên chúng ta có thể sử dụng -zcờ, tuy nhiên theo nghiên cứu ở một số vỏ, đặc biệt là ksh88 (theo Stephane Chazelas ), cờ này bị lỗi.

Xem thêm


+1 cho một cách tiếp cận rất thú vị.
WinEunuuchs2Unix

@ WinEunuuchs2Unix Đã chỉnh sửa để làm cho nó thú vị hơn nữa :)
Sergiy Kolodyazhnyy

1

Tôi nghĩ rằng tiêu đề của bài viết là không chính xác, vì ý định trong tin nhắn là để kiểm tra xem $ 1 và $ 2 không phải là null. Ví dụ đã cho chỉ thiếu hai dấu ngoặc kép trong $ 1 và $ 2 để làm việc. Các biến phải được trích dẫn kép để được mở rộng khi so sánh các chuỗi. Nhưng, để kiểm tra xem $ 1 và $ 2 có tồn tại giống như kiểm tra xem $ 2 có tồn tại không, vì nó không tồn tại nếu $ 1 không tồn tại. Lệnh 'if' cũng không cần thiết trong trường hợp này, vì 'test' trả về true / false và sử dụng '&&' là 'then' nếu return là 0 / true:

[ "$2" != '' ] && commands...

Đơn giản hơn, với -n (khác không):

[ -n "$2" ] && commands...

Để "kiểm tra xem $ 1 và $ 2 có null không" sẽ giống như kiểm tra nếu không có tham số:

[ $# -eq 0 ] && commands...
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.