[[]] 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.