Ai đó có thể vui lòng giải thích sự khác biệt giữa -eq
và ==
trong bash scripting?
Có sự khác biệt nào sau đây không?
[ $a -eq $b ]
và [ $a == $b ]
Có phải chỉ đơn giản là nó chỉ ==
được sử dụng khi các biến chứa số?
Ai đó có thể vui lòng giải thích sự khác biệt giữa -eq
và ==
trong bash scripting?
Có sự khác biệt nào sau đây không?
[ $a -eq $b ]
và [ $a == $b ]
Có phải chỉ đơn giản là nó chỉ ==
được sử dụng khi các biến chứa số?
Câu trả lời:
Đó là cách khác: =
và ==
là để so sánh chuỗi, -eq
dành cho số. -eq
là trong cùng một gia đình như -lt
, -le
, -gt
, -ge
, và -ne
, nếu điều đó giúp bạn nhớ được mà.
==
Nhân tiện, là một bash-ism. Tốt hơn là sử dụng POSIX =
. Trong bash cả hai là tương đương, và trong sh đơn giản =
là người duy nhất được đảm bảo để làm việc.
$ a=foo
$ [ "$a" = foo ]; echo "$?" # POSIX sh
0
$ [ "$a" == foo ]; echo "$?" # bash specific
0
$ [ "$a" -eq foo ]; echo "$?" # wrong
-bash: [: foo: integer expression expected
2
(Lưu ý bên: Trích dẫn những mở rộng biến đổi đó! Đừng bỏ qua các trích dẫn kép ở trên.)
Nếu bạn đang viết một #!/bin/bash
kịch bản thì tôi khuyên bạn nên sử dụng [[
thay thế . Hình thức nhân đôi có nhiều tính năng hơn, cú pháp tự nhiên hơn và ít vấn đề hơn sẽ khiến bạn gặp khó khăn. Dấu ngoặc kép không còn cần thiết xung quanh $a
, cho một:
$ [[ $a == foo ]]; echo "$?" # bash specific
0
Xem thêm:
[[ $var = $pattern ]]
, nếu bạn muốn gì nếu không sẽ được hiểu như là một mô hình fnmatch để thay thể được hiểu như là một chuỗi chữ. Chuỗi foo
không có giải thích phi nghĩa đen, làm cho trích dẫn hoàn toàn an toàn; Chỉ khi OP muốn khớp, giả sử, foo*
(với dấu hoa thị là nghĩa đen, không có nghĩa là bất cứ điều gì có thể xảy ra sau chuỗi foo
) mà trích dẫn hoặc thoát là cần thiết.
[[
không được trích dẫn bên trong là một bashism (chỉ ra rằng đó là lý do duy nhất bạn không đưa ra câu trả lời +1).
[ ... ]
và dấu bằng đôi ==
. : - /
Nó phụ thuộc vào Kiểm tra Xây dựng xung quanh toán tử. Tùy chọn của bạn là dấu ngoặc kép, dấu ngoặc kép, dấu ngoặc đơn hoặc phép thử
Nếu bạn sử dụng ((...)) , bạn đang kiểm tra vốn chủ sở hữu số học ==
như trong C:
$ (( 1==1 )); echo $?
0
$ (( 1==2 )); echo $?
1
(Lưu ý: 0
có nghĩa là true
theo nghĩa Unix và khác không là một thử nghiệm thất bại)
Sử dụng -eq
bên trong dấu ngoặc kép là một lỗi cú pháp.
Nếu bạn đang sử dụng [...] (hoặc nẹp đơn) hoặc [[...]] (hoặc nẹp đôi) hoặc test
bạn có thể sử dụng một trong các -eq, -ne, -lt, -le, -gt hoặc -ge như một so sánh số học .
$ [ 1 -eq 1 ]; echo $?
0
$ [ 1 -eq 2 ]; echo $?
1
$ test 1 -eq 1; echo $?
0
Bên ==
trong của dấu ngoặc đơn hoặc kép (hoặc test
lệnh) là một trong các toán tử so sánh chuỗi :
$ [[ "abc" == "abc" ]]; echo $?
0
$ [[ "abc" == "ABC" ]]; echo $?
1
Là một toán tử chuỗi, =
tương đương ==
và lưu ý khoảng trắng xung quanh =
hoặc ==
yêu cầu của nó.
Trong khi bạn có thể làm [[ 1 == 1 ]]
hoặc [[ $(( 1+1 )) == 2 ]]
nó đang kiểm tra đẳng thức chuỗi - không phải là đẳng thức số học.
Vì vậy, -eq
tạo ra kết quả có thể mong đợi rằng giá trị số nguyên 1+1
bằng với 2
mặc dù RH là một chuỗi và có khoảng trắng ở cuối:
$ [[ $(( 1+1 )) -eq "2 " ]]; echo $?
0
Trong khi so sánh chuỗi của cùng một khoảng không gian theo dõi và do đó, so sánh chuỗi không thành công:
$ [[ $(( 1+1 )) == "2 " ]]; echo $?
1
Và một so sánh chuỗi sai có thể tạo ra câu trả lời sai hoàn toàn. '10' là từ vựng nhỏ hơn '2', do đó, một so sánh chuỗi trả về true
hoặc 0
. Vì vậy, nhiều người bị cắn bởi lỗi này:
$ [[ 10 < 2 ]]; echo $?
0
so với bài kiểm tra đúng cho 10 là số ít hơn 2:
$ [[ 10 -lt 2 ]]; echo $?
1
Trong các bình luận, có một câu hỏi về lý do kỹ thuật sử dụng số nguyên -eq
trên chuỗi trả về True cho các chuỗi không giống nhau:
$ [[ "yes" -eq "no" ]]; echo $?
0
Lý do là Bash được tháo gỡ . Các -eq
nguyên nhân khiến các chuỗi được hiểu là số nguyên nếu có thể bao gồm chuyển đổi cơ sở:
$ [[ "0x10" -eq 16 ]]; echo $?
0
$ [[ "010" -eq 8 ]]; echo $?
0
$ [[ "100" -eq 100 ]]; echo $?
0
Và 0
nếu Bash nghĩ rằng nó chỉ là một chuỗi:
$ [[ "yes" -eq 0 ]]; echo $?
0
$ [[ "yes" -eq 1 ]]; echo $?
1
Như vậy [[ "yes" -eq "no" ]]
là tương đương với[[ 0 -eq 0 ]]
Lưu ý cuối cùng: Nhiều phần mở rộng cụ thể của Bash cho Cấu trúc kiểm tra không phải là POSIX và do đó sẽ thất bại trong các trình bao khác. Các vỏ khác thường không hỗ trợ [[...]]
và ((...))
hoặc==
.
[[ "yes" -eq "no" ]]
trở về True. Làm thế nào để bash ép các chuỗi này thành các giá trị nguyên có thể được so sánh? ;-)
==
trong các mẫu mã và chỉ đề cập (di động, tiêu chuẩn hóa) =
bên dưới.
==
là một bí danh dành riêng cho bash =
và nó thực hiện so sánh chuỗi (từ vựng) thay vì so sánh số. eq
là một so sánh số của khóa học.
Cuối cùng, tôi thường thích sử dụng mẫu if [ "$a" == "$b" ]
==
ở đây là hình thức xấu, vì chỉ =
được chỉ định bởi POSIX.
==
thì hãy đặt nó ở giữa [[
và ]]
. (Và đảm bảo rằng dòng đầu tiên trong tập lệnh của bạn chỉ định sử dụng /bin/bash
.)
Guys: Một số câu trả lời cho thấy các ví dụ nguy hiểm. Ví dụ của OP [ $a == $b ]
được sử dụng cụ thể thay thế biến không được trích dẫn (kể từ chỉnh sửa 17 tháng 10). Cho [...]
rằng đó là an toàn cho bình đẳng chuỗi.
Nhưng nếu bạn sắp liệt kê các lựa chọn thay thế như thế [[...]]
, bạn cũng phải thông báo rằng phía bên tay phải phải được trích dẫn. Nếu không được trích dẫn, đó là một mô hình phù hợp! (Từ trang bash man: "Bất kỳ phần nào của mẫu có thể được trích dẫn để buộc nó được khớp dưới dạng chuỗi.").
Ở đây trong bash, hai câu lệnh mang lại "có" là khớp mẫu, ba câu khác là chuỗi bằng:
$ rht="A*"
$ lft="AB"
$ [ $lft = $rht ] && echo yes
$ [ $lft == $rht ] && echo yes
$ [[ $lft = $rht ]] && echo yes
yes
$ [[ $lft == $rht ]] && echo yes
yes
$ [[ $lft == "$rht" ]] && echo yes
$
[ "$lht" = "$rht" ]
trích dẫn để đáng tin cậy ngay cả đối với bình đẳng. Nếu bạn có một tệp được tạo touch 'Afoo -o AB'
, [ $lft = $rht ]
sẽ trả về true, mặc dù tên tệp đó hoàn toàn không giống với AB
.
[[
nói chung là một ksh-ism có từ thời những năm 1980 mà bash (và nhiều vỏ khác) được thông qua. Đó là toàn bộ vấn đề - nếu bạn có[[
tất cả , thì bạn có thể giả định một cách an toàn rằng tất cả các tiện ích mở rộng ksh được triển khai xung quanh nó (fnmatch()
khớp mẫu kiểu, biểu thức chính quy ERE với=~
, và vâng, ngăn chặn phân tách chuỗi và toàn cầu hóa hệ thống tệp) sẽ có sẵn. Do[[
toàn bộ cú pháp không phải là POSIX, nên không có sự mất tính di động bổ sung nào khi cho rằng các tính năng mà nó được sinh ra sẽ có sẵn.