Bisakah seseorang tolong jelaskan perbedaan antara -eqdan ==dalam skrip bash?
Apakah ada perbedaan antara yang berikut ini?
[ $a -eq $b ]
dan [ $a == $b ]
Apakah hanya itu yang ==hanya digunakan ketika variabel berisi angka?
Bisakah seseorang tolong jelaskan perbedaan antara -eqdan ==dalam skrip bash?
Apakah ada perbedaan antara yang berikut ini?
[ $a -eq $b ]
dan [ $a == $b ]
Apakah hanya itu yang ==hanya digunakan ketika variabel berisi angka?
Jawaban:
Ini sebaliknya: =dan ==untuk perbandingan string, -eqadalah untuk numerik. -eqadalah dalam keluarga yang sama seperti -lt, -le, -gt, -ge, dan -ne, jika yang membantu Anda ingat yang mana.
==omong-omong, omong-omong. Lebih baik menggunakan POSIX =. Dalam bash keduanya sama, dan di sh polos =adalah satu-satunya yang dijamin untuk bekerja.
$ 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
(Catatan: Kutip ekspansi variabel itu! Jangan tinggalkan tanda kutip ganda di atas.)
Jika Anda menulis #!/bin/bashskrip maka saya sarankan menggunakan [[sebagai gantinya . Bentuk ganda memiliki lebih banyak fitur, sintaksis yang lebih alami, dan lebih sedikit Gotcha yang akan membuat Anda tersandung. Kutipan ganda tidak lagi diperlukan $a, misalnya:
$ [[ $a == foo ]]; echo "$?" # bash specific
0
Lihat juga:
[[ $var = $pattern ]], jika Anda ingin apa yang seharusnya dapat diartikan sebagai pola fnmatch untuk bukan diartikan sebagai string literal. String footidak memiliki interpretasi non-literal, membuat meninggalkan kutipan sepenuhnya aman; itu hanya jika OP ingin mencocokkan, katakanlah, foo*(dengan tanda bintang sebagai literal, tidak berarti apa pun yang dapat muncul setelah string foo) yang mengutip atau melarikan diri akan diperlukan.
[[tanda kutip di dalam menjadi bashism (menunjukkan bahwa itu adalah satu-satunya alasan Anda tidak memberikan jawaban +1).
[ ... ]dan dobel tanda sama dengan ==. : - /
Itu tergantung pada Uji Konstruksi di sekitar operator. Pilihan Anda adalah tanda kurung ganda, kawat gigi ganda, kawat gigi tunggal, atau tes
Jika Anda menggunakan ((...)) , Anda menguji ekuitas aritmatika dengan ==seperti pada C:
$ (( 1==1 )); echo $?
0
$ (( 1==2 )); echo $?
1
(Catatan: 0berarti truedalam arti Unix dan bukan nol adalah tes gagal)
Menggunakan -eqbagian dalam tanda kurung ganda adalah kesalahan sintaksis.
Jika Anda menggunakan [...] (atau penjepit tunggal) atau [[...]] (atau penjepit ganda), atau testAnda dapat menggunakan salah satu dari -eq, -ne, -lt, -le, -gt, atau -ge sebagai perbandingan aritmatika .
$ [ 1 -eq 1 ]; echo $?
0
$ [ 1 -eq 2 ]; echo $?
1
$ test 1 -eq 1; echo $?
0
Bagian ==dalam kawat gigi tunggal atau ganda (atau testperintah) adalah salah satu operator perbandingan string :
$ [[ "abc" == "abc" ]]; echo $?
0
$ [[ "abc" == "ABC" ]]; echo $?
1
Sebagai operator string, =sama dengan ==dan perhatikan spasi putih di sekitar =atau ==yang diperlukan.
Meskipun Anda dapat melakukan [[ 1 == 1 ]]atau [[ $(( 1+1 )) == 2 ]]sedang menguji kesetaraan string - bukan kesetaraan aritmatika.
Jadi -eqmenghasilkan hasil yang mungkin diharapkan bahwa nilai integer 1+1sama dengan 2meskipun RH adalah string dan memiliki ruang tambahan:
$ [[ $(( 1+1 )) -eq "2 " ]]; echo $?
0
Sementara perbandingan string yang sama mengambil ruang tambahan dan karenanya perbandingan string gagal:
$ [[ $(( 1+1 )) == "2 " ]]; echo $?
1
Dan perbandingan string yang salah dapat menghasilkan jawaban yang salah sepenuhnya. '10' secara leksikografis kurang dari '2', sehingga perbandingan string mengembalikan trueatau 0. Begitu banyak yang digigit oleh bug ini:
$ [[ 10 < 2 ]]; echo $?
0
vs tes yang benar untuk 10 secara aritmetika kurang dari 2:
$ [[ 10 -lt 2 ]]; echo $?
1
Dalam komentar, ada pertanyaan tentang alasan teknis menggunakan integer -eqpada string mengembalikan True untuk string yang tidak sama:
$ [[ "yes" -eq "no" ]]; echo $?
0
Alasannya adalah bahwa Bash tidak diketik . The -eqmenyebabkan string ditafsirkan sebagai bilangan bulat jika mungkin termasuk konversi dasar:
$ [[ "0x10" -eq 16 ]]; echo $?
0
$ [[ "010" -eq 8 ]]; echo $?
0
$ [[ "100" -eq 100 ]]; echo $?
0
Dan 0jika Bash berpikir itu hanya string:
$ [[ "yes" -eq 0 ]]; echo $?
0
$ [[ "yes" -eq 1 ]]; echo $?
1
Jadi [[ "yes" -eq "no" ]]setara dengan[[ 0 -eq 0 ]]
Catatan terakhir: Banyak ekstensi spesifik Bash untuk Konstruk Uji tidak POSIX dan karenanya akan gagal di shell lain. Kerang lain umumnya tidak mendukung [[...]]dan ((...))atau== .
[[ "yes" -eq "no" ]]mengembalikan True. Bagaimana bash memaksa string ini ke nilai integer yang dapat dibandingkan? ;-)
[[ "yes" -eq "no" ]]sama dengan [[ "yes" -eq 0 ]] atau [[ "yes" -eq "any_noninteger_string" ]]- Semua Benar. The -eqpasukan bilangan bulat perbandingan. Ini "yes"ditafsirkan sebagai bilangan bulat 0; perbandingannya Benar jika bilangan bulat lainnya baik 0atau hasil string 0.
==dalam sampel kode dan hanya menyebutkan (portabel, standar) di =bawahnya.
==adalah alias spesifik-bash untuk =dan melakukan perbandingan string (leksikal) alih-alih perbandingan numerik. eqmenjadi perbandingan angka tentu saja.
Akhirnya, saya biasanya lebih suka menggunakan formulir if [ "$a" == "$b" ]
==sini adalah bentuk yang buruk, karena hanya =ditentukan oleh POSIX.
==maka letakkan di antara [[dan ]]. (Dan pastikan bahwa baris pertama skrip Anda ditentukan untuk digunakan /bin/bash.)
Guys: Beberapa jawaban menunjukkan contoh berbahaya. Contoh OP [ $a == $b ]secara khusus menggunakan substitusi variabel yang tidak dikutip (per Oktober '17 sunting). Untuk [...]itu aman untuk kesetaraan string.
Tetapi jika Anda akan menghitung alternatif seperti [[...]], Anda harus memberi tahu juga bahwa sisi kanan harus dikutip. Jika tidak dikutip, itu adalah pencocokan pola! (Dari halaman bash man: "Bagian mana pun dari pola dapat dikutip untuk memaksa agar dicocokkan sebagai string.").
Di sini, di bash, dua pernyataan yang menghasilkan "ya" adalah pencocokan pola, tiga lainnya adalah persamaan string:
$ 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" ] dengan kutipan agar dapat diandalkan bahkan untuk kesetaraan. Jika Anda memiliki file yang dibuat touch 'Afoo -o AB', [ $lft = $rht ]akan mengembalikan true, meskipun nama file itu sama sekali tidak identik AB.
[[secara keseluruhan adalah ksh-isme era 1980-an yang diadopsi oleh bash (dan banyak kerang lainnya). Itulah intinya - jika Anda memiliki[[semuanya , maka Anda dapat dengan aman mengasumsikan bahwa semua ekstensi ksh diimplementasikan di sekitarnya (fnmatch()pencocokan pola-gaya, ERE ekspresi reguler dengan=~, dan ya, penindasan string-splitting dan penggumpalan sistem file) akan menjadi tersedia. Karena[[sintaksinya adalah non-POSIX secara keseluruhan, tidak ada kerugian portabilitas tambahan dengan mengasumsikan bahwa fitur yang dilahirkannya akan tersedia.