Bash Eşitlik Operatörleri (==, -eq)


136

Lütfen birisi bash betikleri arasındaki -eqve ==içindeki farkı açıklayabilir mi?

Aşağıdakiler arasında herhangi bir fark var mı?

[ $a -eq $b ] ve [ $a == $b ]

Bu sadece ==değişkenler sayı içerdiğinde mi kullanılır?

Yanıtlar:


187

Bunun tam tersi: =ve ==dizi karşılaştırmaları içindir, -eqsayısal olanlar içindir. -eqaynı aileden olduğu -lt, -le, -gt, -ge, ve -nebu size hangisinin hangisi hatırlamıyorum yardımcı olur.

==bu arada, bir bash-ism. POSIX kullanmak daha iyidir =. Bash'de ikisi eşdeğerdir ve düz olarak sh =, çalışması garantili tek kişidir.

$ 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

(Yan not: Bu değişken genişletmeleri alıntılayın! Yukarıdaki çift tırnak işaretlerini atlamayın.)

Bir #!/bin/bashkomut dosyası yazıyorsanız, onun yerine kullanmanızı[[ öneririm . İkiye katlanmış formda daha fazla özellik, daha doğal sözdizimi ve sizi ayağa kaldıracak daha az sorun vardır. $aBiri için artık çift tırnak işareti gerekmez :

$ [[ $a == foo ]]; echo "$?"      # bash specific
0

Ayrıca bakınız:


1
@DJCrashdummy, [[bir bütün olarak , bash'ın (ve diğer birçok kabuğun) benimsediği 1980'lerden kalma bir ksh- izm'dir . Eğer varsa - Bütün mesele olduğunu [[ hiç , o zaman güvenli bir şekilde tüm uzantılar (etrafına uygulanan KSh varsayabiliriz fnmatch()tarzı desen eşleştirme, ile ERE düzenli ifadeler =~ve evet, dize bölünme bastırılması ve dosya sistemi globbing) olacaktır mevcut. Bir [[bütün olarak POSIX olmayan sözdizimi olduğundan, birlikte doğduğu özelliklerin mevcut olacağı varsayılırken ek taşınabilirlik kaybı olmaz.
Charles Duffy

1
@DJCrashdummy ... link size tırnak işaretleri bazen üzerinde gerekli olduğunu doğru noktalarını göstermek sağ taraftaki ait [[ $var = $pattern ]]aksi takdirde yerine değişmez dize olarak yorumlanmalıdır bir fnmatch deseni olarak yorumlanabilir ne isterseniz. Dizenin foogerçek olmayan bir yorumu yoktur, bu da tırnak işaretlerini tamamen güvenli hale getirir; sadece OP eşleştirmek isterse foo*(örneğin yıldız işaretiyle, dizeden sonra gelebilecek hiçbir şey anlamına gelmez foo) tırnak işaretleri veya kaçış gerekli olacaktır.
Charles Duffy

@CharlesDuffy maalesef neyi kastettiğin hakkında hiçbir fikrim yok, çünkü yorumum silinmiş gibi ve hatırlayamıyorum çünkü epey zaman oldu. :-(
DJCrashdummy

@DJCrashdummy, ... huh, kendin çektin sandım. Temelde, [[bir bashizm olan içindeki alıntı yapılmamış genişlemelerle ilgili bir itirazdı (yanıta +1 vermemenizin tek nedeninin bu olduğunu gösterir).
Charles Duffy

@CharlesDuffy hayır, tek neden bu değil: basit görevler için bash-isms, ksh-isms vb. Sevmememin yanı sıra (bu sadece sorunlara neden oluyor ve yeni başlayanların kafasını karıştırıyor), anlamıyorum neden single mix kaşlı ayraçlar [ ... ]ve çift eşittir ==. : - /
DJCrashdummy

27

Operatörün etrafındaki Test Yapısına bağlıdır . Seçenekleriniz çift parantez, çift parantez, tek parantez veya test şeklindedir

Eğer kullanırsanız ((...)) , sizinle aritmetik eşitlik test ediyoruz ==C olarak:

$ (( 1==1 )); echo $?
0
$ (( 1==2 )); echo $?
1

(Not: Unix anlamında ve sıfır olmayan bir testin başarısız olduğu 0anlamına gelir true)

-eqÇift parantez içinde kullanmak bir sözdizimi hatasıdır.

Eğer kullanıyorsanız [...] (veya tek ayracı) ya da [[...]] (veya çift ayracı) ya da test, sen -eq, -ne, -Bu, -le, -gt birini kullanabilir veya aritmetik karşılaştırma olarak -ge .

$ [ 1 -eq 1 ]; echo $?
0
$ [ 1 -eq 2 ]; echo $?
1
$ test 1 -eq 1; echo $?
0

==Tek veya çift süslü (veya iç testkomutunun) biridir dize karşılaştırma operatörleri :

$ [[ "abc" == "abc" ]]; echo $?
0
$ [[ "abc" == "ABC" ]]; echo $?
1

Bir dize operatörü olarak, =eşdeğerdir ==ve çevresinde boşluk not =ya ==da gerektiriyordu.

Eğer iken edebilirsiniz yapmak [[ 1 == 1 ]]ya [[ $(( 1+1 )) == 2 ]]da dize eşitliğinin test ediyor - değil aritmetik eşitlik.

Dolayısıyla , RH bir dize olmasına ve sonunda bir boşluğa sahip olmasına rağmen, büyük olasılıkla tamsayı değerinin eşit olması beklenen -eqsonucu üretir :1+12

$ [[ $(( 1+1 )) -eq  "2 " ]]; echo $?
0

Aynı şeyin bir dize karşılaştırması sondaki boşluğu alır ve bu nedenle dize karşılaştırması başarısız olur:

$ [[ $(( 1+1 )) ==  "2 " ]]; echo $?
1

Ve hatalı bir dizi karşılaştırması tamamen yanlış cevabı verebilir. '10' sözlükbilimsel olarak '2'den küçüktür, bu nedenle bir dize karşılaştırması trueveya döndürür 0. Pek çok kişi bu böcek tarafından ısırıldı:

$ [[ 10 < 2 ]]; echo $?
0

aritmetik olarak 2'den küçük 10 için doğru teste kıyasla:

$ [[ 10 -lt 2 ]]; echo $?
1

Yorumlarda, dizelerde tamsayı kullanmanın teknik nedeni -eqile aynı olmayan dizeler için True döndüren bir soru vardır :

$ [[ "yes" -eq "no" ]]; echo $?
0

Bunun nedeni, Bash'in türsüz olmasıdır . -eqDizeleri tamsayı olarak yorumlanır neden olur mümkünse taban dönüşüm dahil:

$ [[ "0x10" -eq 16 ]]; echo $?
0
$ [[ "010" -eq 8 ]]; echo $?
0
$ [[ "100" -eq 100 ]]; echo $?
0

Ve 0Bash bu sadece bir dizedir düşünürse:

$ [[ "yes" -eq 0 ]]; echo $?
0
$ [[ "yes" -eq 1 ]]; echo $?
1

Yani [[ "yes" -eq "no" ]]eşdeğerdir[[ 0 -eq 0 ]]

Son not: Test Yapılarına yönelik Bash'e özgü uzantıların çoğu POSIX değildir ve bu nedenle diğer kabuklarda başarısız olur. Diğer mermiler genellikle [[...]]ve ((...))veya desteklemez== .


Merak ettiğim teknik nedenden için [[ "yes" -eq "no" ]]doğru döndüren. Bash bu dizeleri karşılaştırılabilecek tam sayı değerlerine nasıl zorlar? ;-)
odony

4
Bash değişkenler türsüz böylece [[ "yes" -eq "no" ]]eşdeğerdir [[ "yes" -eq 0 ]] ya [[ "yes" -eq "any_noninteger_string" ]]hepsi gerçek -. -eqKuvvetler karşılaştırma tamsayı. "yes"Bir tam sayı olarak yorumlanır 0; diğer tam sayılardan biri 0veya dize sonucu ise karşılaştırma True olur 0.
dawg

Boo, ıslık yeniden: ==kod örneklerinde gösteriliyor (taşınabilir değil) ve altında yalnızca (taşınabilir, standartlaştırılmış) bahsediliyor =.
Charles Duffy

24

==için bash'a özgü bir takma addır =ve sayısal bir karşılaştırma yerine bir dizge (sözcüksel) karşılaştırması gerçekleştirir. eqtabii ki sayısal bir karşılaştırma.

Son olarak, genellikle formu kullanmayı tercih ediyorum if [ "$a" == "$b" ]


15
Kullanılması ==burada da sadece kötü biçimidir =POSIX tarafından belirlenir.
Charles Duffy

9
Gerçekten kullanmak ısrar ederse ==o zaman arasına koyun [[ve ]]. (Ve betiğinizin ilk satırının kullanmayı belirttiğinden emin olun /bin/bash.)
holgero

18

Çocuklar: Birkaç cevap tehlikeli örnekler gösteriyor. OP'nin örneği [ $a == $b ]özellikle alıntılanmamış değişken ikamesi kullandı (Ekim '17 düzenlemesinden itibaren). İçin [...]bu dize eşitlik için güvenlidir.

Ancak [[...]], gibi alternatifleri sıralayacaksanız , sağ taraftan alıntı yapılması gerektiğini de bildirmelisiniz. Alıntı yapılmamışsa, bu bir model eşleşmesidir! (Bash man sayfasından: "Desenin herhangi bir bölümü, onu bir dizge olarak eşleşmeye zorlamak için alıntılanabilir.").

Burada bash'de, "evet" sonucunu veren iki ifade örüntü eşleştirmedir, diğer üçü dizge eşitliğidir:

$ 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
$

2
İhtiyaç olması [ "$lht" = "$rht" ] tırnak eşitlik için güvenilir bile olmak. Eğer oluşturulmuş bir dosyanız varsa touch 'Afoo -o AB', [ $lft = $rht ]bu dosya adı olduğu halde, gerçek dönecektir hiç değil dizisidir AB.
Charles Duffy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.