[[$ A == z *]] ve [$ a == z *] arasındaki fark nedir?


35

Bu ikisi arasında herhangi bir fark var mı.

[[ $a == z* ]]

ve

[ $a == z* ] 

Farklı çıktılara sahip olacakları bir örnek alabilir miyim?

Üstelik, çalışma şekli nasıl [[ ]]farklılık gösteriyor [ ]?

Yanıtlar:


41

Arasındaki fark [[ … ]]ve [ … ]daha çok kaplı Bash - tek veya çift bir ayraç kullanılarak . En önemlisi, [[ … ]]özel bir sözdizimi, oysa [bir komut için komik görünümlü bir isim. [[ … ]]içinde olanlar için özel sözdizimi kuralları vardır [ … ], değildir.

Bir joker karakterin eklenmiş kırışmasıyla, işte nasıl [[ $a == z* ]]değerlendirilir:

  1. Komutu ayrıştırın: [[ … ]]koşullu ifadenin etrafındaki koşullu yapı budur $a == z*.
  2. Koşullu ifadeyi ayrıştırın: Bu, ==operandlarla $ave ikili işlecidir z*.
  3. İlk işleneni değişkenin değerine genişletin a.
  4. ==İşleci değerlendirin : değişkenin değerinin akalıpla eşleşip eşleşmediğini test edin z*.
  5. Koşullu ifadeyi değerlendirin: sonucu koşullu işlecin sonucudur.
  6. Komut şimdi değerlendirilir, koşullu ifade doğru ise 0, yanlış ise 1 olur.

İşte nasıl [ $a == z* ]değerlendirilir:

  1. Komutu Ayrıştırma: şudur [kelimeleri değerlendirerek oluşturduğu argüman komut $a, ==, z*, ].
  2. $aDeğişkenin değerine genişletin a.
  3. Komut parametrelerinde sözcük ayırma ve dosya adı oluşturma işlemini gerçekleştirin.
    • Örneğin, değeri ise a6 karakterlik dizedir foo b*(örneğin elde edilen a='foo b*') ve (geçerli dizinin dosyaların listesi bar, baz, qux, zim, zum), sonra genişleme sonucu kelimelerin aşağıdaki listesi: [, foo, bar, baz, ==, zim, zum, ].
  4. Komutu [önceki adımda elde edilen parametrelerle çalıştırın .
    • Yukarıdaki örnek değerlerle, [komut bir sözdizimi hatasından şikayet eder ve 2 durumunu döndürür.

Not: [[ $a == z* ]]3. adımda, değeri akelime bölme işlemine ve dosya adı oluşturulmasına maruz kalmaz, çünkü tek bir kelimenin beklendiği bir bağlamdadır (koşullu işlecin sol argümanı ==). Çoğu durumda, tek bir kelime bu konumda mantıklıysa, değişken genişleme çift tırnak işareti gibi davranır. Bununla birlikte, bu kuralın bir istisnası vardır: içinde [[ abc == $a ]], ajoker karakter içeriyorsa a, joker desenle eşleştirilir. Değeri Örneğin, abir a*o [[ abc == $a ]]doğrudur (joker çünkü *içinde tırnaksız genişleme gelen $amaçları *) oysa [[ abc == "$a" ]](yanlıştır sıradan karakteri nedeniyle*alıntı genişlemesinden gelen $aeşleşmiyor bc). İçeride [[ … ]], çift tırnak, bir fark yapmazlar dize eşleştirme operatörlerin sağ tarafta dışında ( =, ==, !=ve =~).


39

[testkomut için bir diğer addır. Unix Versiyon 6'nın bir ifemri vardı ancak Versiyon 7 (1979) , if-then-else-elif-fi konstrüksiyonu da dahil olmak üzere birkaç programlama yapısına sahip olan yeni Bourne kabuğuyla birlikte geldi ve Unix versiyon 7 , çoğu Eski sürümlerde komut tarafından gerçekleştirilen "testler" .testif

[testUnix System III (1981) 'de bir takma isim yapıldı ve her ikisi de kabuğun içine yerleştirildi . Bazı Unix varyantlarının bundan [sonraya kadar bir emri bulunmadığı belirtilmelidir , ancak Almquist kabuğuna dayanan bazı shBSD'lerde 2000'li yılların başlarına kadar (bir testyerleşik her zaman ashkaynağa dahil edildi , ancak BSD'ler başlangıçta devre dışı bırakıldı)).

Not testaka ["testler" yapmak için bir komut olduğunu, eşitlik operatörü bu yüzden, bu yüzden bir atama ve eşitlik operatörü arasındaki belirsizliği giderecek hiçbir neden yok, o komut yaptığı hiçbir atama yoktur =. ==sadece birkaç yeni uygulama tarafından desteklenir [(ve sadece bir takma addır =).

Çünkü [hiçbir şey daha bir komutla birden, o kabuk tarafından başka komutla aynı şekilde ayrıştırılır.

Spesifik olarak, örneğinizde, $aalıntılanmadığı için, normal kelime bölme kurallarına göre birkaç kelimeye bölünür ve her kelime, muhtemelen daha fazla kelimeyle sonuçlanacak şekilde isimlendirmek için isimlendirir. [komuta ayrı bir argüman .

Benzer şekilde, z*şu anki dizinden başlayarak geçerli dizindeki dosya listesine genişletilecektir z.

Yani örneğin $abir b* = xve orada z1, z2, b1ve b2geçerli dizinde dosyaları [komut 9 argümanları alacağı: [, b1, b2, =, x, ==, z1, z2ve ].

[bağımsız değişkenlerini koşullu ifade olarak ayrıştırır. Bu 9 argüman geçerli bir koşullu ifadeye eklenmez, bu nedenle büyük olasılıkla bir hata verecektir.

[[ ... ]]Yapı muhtemelen etrafında 1988 olarak Korn kabuk tarafından tanıtıldı ksh86aiken 1987 yılında o yoktu ksh88baştan vardı.

Ksh (tüm uygulamalar) dışında, [[...]]bash (sürüm 2.02'den beri) ve zsh tarafından da desteklenir, ancak üç uygulama da farklıdır ve değişiklikler genel olarak geriye dönük uyumlu olsa da aynı kabuğun her sürümü arasında farklılıklar vardır (önemli bir istisna hariç =~Davranışı değiştiğinde belirli bir sürümden sonra birkaç komut dosyasını kırdığı bilinen operatör). [[...]]POSIX veya Unix veya Linux (LSB) tarafından belirtilmez. Birkaç kez dahil edilmek için düşünülmüş, ancak ana mermiler tarafından desteklenen ortak işlevselliğinin zaten [komut ve case-in-esacyapı tarafından ele alındığı için dahil edilmemiştir .

Bütün [[ ... ]]yapı bir emirdir. Yani, bir çıkış statüsüne sahiptir (koşullu ifadeyi değerlendirmenin sonucu olduğu için en önemli varlığıdır), onu başka bir komuta gönderebilirsiniz (faydalı olmasa da) ve genel olarak istediğiniz yerde kullanabilirsiniz. başka bir komut kullanın (yalnızca kabuğun içinde, kabuğun yapısı olduğu için), ancak normal bir basit komut gibi ayrıştırılmaz. İçindeki şey kabuklu tarafından koşullu ifade olarak ayrıştırılır ve kelime bölme ve dosya adı oluşturmanın olağan kuralları farklı uygulanır.

[[ ... ]]==en baştan biliyor ve =1 ile eşdeğer . Ksh bir gaf olduğunu olsa (ve karışıklık ve birçok böcek neden olan) =ve ==bir eşitlik operatörü ama (gerçi bir desen eşleştirme operatörü olmayan eşleme boy alıntı ile değil kabuğuna kabuk farklılık belirsiz kurallara devre dışı bırakılabilir).

Yukarıdaki kodunuzda [[ $a == z* ]]kabuk, alışılmış olanlara benzer kurallarda birkaç belirteçte ayrıştırır, onu bir kalıp eşleştirme karşılaştırması olarak tanır z*, adeğişkenin içeriğiyle eşleşecek bir kalıp olarak değerlendirir .

Genelde, kendini ayaklarıyla vurmak [[ ... ]], [komutta olduğundan daha zor . Ama birkaç kural gibi

  • her zaman değişkenleri alıntı
  • -aveya -ooperatörünü asla kullanmayın (birkaç [komut ve &&ve || kabuk operatörlerini kullanın)

[POSIX kabukları ile güvenilir olun .

[[...]]farklı kabuklarda -ntregexp eşleşen operatörler gibi ekstra operatörleri destekler ... ancak liste ve davranış, kabuktan kabuğa ve sürümden sürüme değişir.

Bu nedenle, betiğinizin hangi kabuk ve minimum sürümle yorumlanacağını bilmiyorsanız, standart [komutla bağlantı yapmak muhtemelen daha güvenlidir .


1 Bir istisna: [[...]]sürümde bash'a eklendi 2.02. Kadar 2.03değişti nerede, [[ x = '?' ]]ise gerçek döneceğini [[ x == '?' ]]return false olacaktır. Bu alıntı, =işleci bu sürümlerde kullanırken desen eşleşmesini engellemedi , ancak kullanırken kullandı ==.


Harika bilgi Lütfen neden "-a veya -o işlecini kullanmadığınızı" açıklar mısınız?
grebneke

@grebneke, denemek [ '!' = foo -o a = a ]içinde bashmesela.
Stéphane Chazelas

0

her ikisi de ifadeleri değerlendirmek için kullanılır ve [[POSIX'in eski kabuklu kabuğu ile çalışmaz ve [[ayrıca desen eşleşmesini ve regex'i destekler). örnek bunları dene

[ $n -eq 0 -a $y -eq 0 ] && echo "Error" || echo "Ok"

[[ $n -eq 0 && $y -eq 0 ]] && echo "Error" || echo "Ok"


Bourne kabuğunun POSIX olmadığını, [[...]]bazı sürümlerin regexp'leri desteklediğini, bazı sürümlerin de [regexp eşleşmesini desteklediğini unutmayın. Aritmetik karşılaştırma için, destekleyen mermilerde [[yazmayı tercih edersiniz(( n == 0 && y == 0))
Stéphane Chazelas
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.