[[]] Testinde neden çift tırnak kullanılmalı?


23

Bir bash betiğinde 2 tamsayımız olduğunu varsayalım:

value1=5
value2=3

Öyleyse neden bir test durumunda çift tırnak kullanmamız gerekiyor? Örneğin:

if [[ "$value1" -eq "$value2" ]]

Neden sadece aşağıdakileri kullanmıyorsunuz?

if [[ $value1 -eq $value2 ]]

Bana göre çift tırnak bir anlam ifade etmiyor.


5
Kabukta aktaran dizeleriyle ilgisi yoktur Bu kelime bölme gerçekleştirmesini kabuğu önlenmesi olduğudur (veri türleri gibi.) (Ve açılımları diğer tür.)
filbranden

13
Terdon'un belirttiği gibi, bu özel yapıda değişkenlerin alıntılanması gerekli değildir (ve elbette, herhangi bir yerde tek kelimeli değerlerle), varyasyonlarınızı her zaman alıntılamak için tavsiye vermek isterim . Hangi bağlamda değişkenleri işaretsiz bırakabileceğinizi gerçekten biliyor musunuz? Alıntı yapmanın nedeni, gerekip gerekmediği 5ve 3sürdürülebilmesidir. Değerler daha sonra değişebilir ve ortaya çıkan hatalar açık olmayabilir.
Peter - Monica,

2
@sudodus Bunun [[ ]]sadece bunun için doğru olduğunu sanmıyorum [ ].
Benjamin W.

1
Haklısın, @BenjaminW. Kelime bölme, değişkenler için çift tırnak kullanmanın iyi bir fikir olmasının tek nedeni değildir. Bir değişken boş olduğunda durum da vardır. İçerdeydi açıklama yapacak [] hata vererek örnek [2 -eq] için (başarısız, ama [[]] () kelimesi bölünme ile vaka gibi savunmasız değildir.
sudodus

2
@ marcelm, Bash, ksh ve Zsh tamsayı değişkenlerine sahiptir ve [[ ]]bunlar içinde de tamsayıların işleyişlerini zorlamaktadır -eq.
ilkkachu

Yanıtlar:


7

Kelime bölme.

Bu örnek çok imkansızdır, ancak mümkündür , bu nedenle, savunma kodunu yazmak istiyorsanız izlerinizi tırnak işaretleri ile örtün:

$ set -x
$ value1=5
+ value1=5
$ value2=3
+ value2=3
$ [ $value1 -eq $value2 ]
+ '[' 5 -eq 3 ']'

Tamam, şimdiye kadar hepsi iyi. İngiliz anahtarı dişlilerin içine atalım:

$ IFS=456
+ IFS=456
$ [ $value1 -eq $value2 ]
+ '[' '' -eq 3 ']'
bash: [: : integer expression expected

Hata.

$ [ "$value1" -eq "$value2" ]
+ '[' 5 -eq 3 ']'

Ahh.


2
Ancak OP çift parantez kullanıyor, bu nedenle kelime bölme gerçekleşmiyor.
user000001

5
Evet, bu gerçekten bash'ın [[ ]]yapısına bağlı değil.
terdon

1
Eh? [ $value1 -eq $value2 ]boş bir sol tarafta hayır value1olacaktı . '[' -eq 3 ']'''
Charles Duffy

Ben de şaşırdım ama kanıtlar var.
glenn jackman

1
Bu cevap doğrudan soru ile ilgili değildir . Kabul edildiğine şaşırdım. Topluluk wiki'si olarak ayarlama.
glenn jackman

35

Aslında burada alıntılara ihtiyacın yok. Bu, işaretlenmemiş bir değişkeni kullanmanın güvenli olduğu çok az durumdan biridir. Bunu şu şekilde onaylayabilirsiniz set -x:

$ var1=""
$ var2="3"
$ set -x
$ if [[ $var1 -eq $var2 ]]; then echo "match!"; else echo "no match!"; fi
+ [[ '' -eq 3 ]]
+ echo 'no match!'
no match!
$ if [[ "$var1" -eq "$var2" ]]; then echo "match!"; else echo "no match!"; fi
+ [[ '' -eq 3 ]]
+ echo 'no match!'
no match!

Yukarıda gördüğünüz gibi, testin alıntılanmış ve alıntılanmamış versiyonları bash ile aynı şekilde çözülür. Aynı zshşey [[ ]]operatörü destekleyen diğer bir kabuk için de geçerli olmalı .

Bu daha taşınabilir olan durum olmadığını unutmayın [ ]:

$ if [ $var1 -eq $var2 ]; then echo "match!"; else echo "no match!"; fi
+ '[' -eq 3 ']'
sh: [: -eq: unary operator expected
+ echo 'no match!'
no match!

[ ]Yapı, aksine [[ ]]biri alıntı gerektirir.


Ne zaman ve neden alıntı yapılması gerektiğiyle ilgili daha fazla bilgi edinmek için bazı faydalı bağlantılar:


Tamsayı değişkenleri olan bu durumda, bunları böyle bildirmek daha iyi olacaktır. declare -i var1=olduğu 0değerlendirildiğinde.
Freddy,

4
Not -eqolan aritmetik bile bırakabilir, böylece karşılaştırma $(içinde out [[ .. ]]) ve yazma [[ a -eq b ]]. Dize karşılaştırma ile, $tabii ki, yani[[ $a = $b ]]
ilkkachu

2
@ user000001 iyi nokta. Tabii ki, bunların genişletilmesini istemeniz çok mümkün . Örneğin, bu bir maç olmasını beklediğiniz: var1="afoob"; var2="a*b"; [[ $var1 = $var2 ]] && echo match. Glob karakterlerini, globbing bağlamında bir glob gibi davranmadan (örneğin [[ ]]) kullanmadan kullanmak istiyorsanız, alıntı yapmanız gerekir, evet.
terdon

3
@ ilkkachu, bu beni şaşırtıyor. "Çıplak" değişkenlerin sadece bir dizi alt dizisinde veya ((...))veya içinde değerlendirilebileceğini düşündüm $((...). İşe benziyor, ama (yaşlı huysuz adam, etkinleştirmek) Sevmiyorum.
glenn jackman

1
@glennjackman, sana söyleyen kişi olduğum için özür dilerim, ama evet, işlenenler -eqve arkadaşlarım [[ ]]da aritmetik bağlamlar. :) (İlgili: bash [[]] komutunun içindeki otomatik değişken genişlemesi )
ilkkachu

17

Çift tırnak gerekli olmasa da, bunları kullanmak için nedenler şunlardır:

  • İyi uygulama / alışkanlık: Bu durumda gerekli değildir, ancak genel olarak çift tırnak , istenmeyen kelimelerin bölünmesini önlemektir.
  • Çünkü value1ve value2değişken vardır ve içerdikleri bilmiyor olabilir. Aksi taktirde, "Neden kontrol etmek yerine değişkenlerle uğraşıyorsunuz if [[ 5 -eq 3 ]]? Veya daha da ileri götürüyorsunuz, neden ifzaten 5'in 3'e eşit olmadığını biliyorsanız neden hiç rahatsız ediyorsunuz?" bu kelime bölme gerçekleşmeyecek [[, ancak kelime bölmenin olmadığı durumlar nadirdir. Yine, ilk noktaya bakınız.)

1

Sorunuzla doğrudan ilgili değil, ancak kullanıyorum

if (($ değer1 == $ değer2)); sonra

Numaraları karşılaştırdığımda ancak tırnak kullanmak zorunda değilsin.


2
if (( value1 == value2 )); then. Aritmetik bağlamlarda, buna bile ihtiyacınız yoktur $. Bununla birlikte, bu sorunun [[ ... ]]testlerde kullanılan değişkenlere odaklandığı görülmektedir .
Kusalananda

1
Biliyorum. Ama açıkçası bu özelliği kullanmıyorum çünkü değişken isimlerimin tutarlı olmasını ve böylece $ 'ı her zaman önek olarak kullanabilmek istiyorum.
31’da

1

Kesinlikle haklısın!

Çift köşeli parantez içindeki alıntılar, en azından bu durumda hiçbir anlam ifade etmemektedir.

Fakat her gün çift tırnak işareti kullandığımdan - özellikle tek köşeli ayraç ifadeleri için, işlevlere ve komut dosyalarına argümanları iletmek, bazen de değişken atamaları (basit dezavantajlar için tamamen yararsızdır) - sanırım bazı insanlar, en azından, içgüdüsel olarak değişken genişlemelerin etrafına çift tırnak yazın .

Çifte alıntı size bir kibarlık duygusu verebilir. Çifte fiyat teklifi olan eve gelmek gibidir. - D. Kummer

Sonuç olarak ve anlaşılır bir şekilde çift tırnak yapmanın bir yararı - ancak yalnızca mantıklı olduğu gibi - bash için yeni olan iş arkadaşlarının daha kararlı senaryolar yazmayı öğrenebilmeleridir . Ayrıca , bash ile veri işleme sanatının, alan ayırıcılar tarafından veri akışlarını (değişkenler dahil) ayırma ve bunları filtreler yoluyla boruya aktarma konusunda daha fazla olduğunu vurgulamaktadır . Veri parçalarınızı akıştan ayırır almaz, çift ​​tırnak işareti ile bir arada tutun!

Başka bir avantaj, bash betiğinin, kod vurgulama editörü içinde çift ​​tırnaklı dizelerle daha iyi okunabilirliği olabilir .

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.