Hakkında bash örnekleri okuyorum ifama bazı örnekler tek köşeli parantez ile yazılmıştır:
if [ -f $param ]
then
#...
fi
çift köşeli parantez ile diğerleri:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
Fark ne?
Hakkında bash örnekleri okuyorum ifama bazı örnekler tek köşeli parantez ile yazılmıştır:
if [ -f $param ]
then
#...
fi
çift köşeli parantez ile diğerleri:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
Fark ne?
Yanıtlar:
Tekil []posix kabuğu uyumlu durum testleridir.
İkili [[]], standardın bir uzantısıdır []ve bash ve diğer kabuklar (örn. Zsh, ksh) tarafından desteklenir. Ekstra işlemleri (standart posix işlemlerinin yanı sıra) desteklerler. Örneğin: ||yerine -ove regex eşleşmesi =~. Koşullu yapılarla ilgili bash manuel bölümünde daha farklı bir farklılık listesi bulunabilir .
[]Komut dosyanızın kabuklar arasında taşınabilir olmasını istediğinizde kullanın . Kullanım [[]]değil tarafından desteklenen koşullu ifadeleri istiyorsanız []ve yapmaması taşınabilir olması gerekir.
[[ ]](örneğin, bash ile #!/bin/bashveya #!/usr/bin/env bash), taşınabilir seçeneği kullanmanız gerektiğini ekleyeceğim . / Bin / sh komutunun bu tür uzantıları desteklediğini düşünen komut dosyaları, durumun böyle olmadığı son Debian ve Ubuntu sürümleri gibi işletim sistemlerini bozacaktır.
Davranış farklılıkları
Bash 4.3.11'de test edilmiştir:
POSIX vs Bash uzantısı:
[ POSIX[[şu adreste belgelenmiş bir Bash uzantısıdır¹: https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructsnormal komut vs büyü
[ sadece garip bir isimle düzenli bir komut.
]sadece [başka bir argümanın kullanılmasını engelleyen bir argüman .
Ubuntu 16.04 aslında /usr/bin/[coreutils tarafından sağlanan bir yürütülebilir dosyaya sahiptir , ancak bash yerleşik sürümü önceliklidir.
Hiçbir şey Bash'in komutu ayrıştırma biçiminde değiştirilmez.
Özellikle, <yeniden yönlendirme &&ve ||birden çok komutu birleştirmek, ( )kaçmadığı sürece alt kabuklar üretir \ve kelime genişletme her zamanki gibi gerçekleşir.
[[ X ]]Xsihirli bir şekilde ayrıştırılan tek bir yapıdır . <, &&, ||Ve ()özel olarak muamele edilmiş ve kelime bölme kuralları farklı olabilirler.
=Ve gibi başka farklılıklar da vardır =~.
Bashese'de: [yerleşik bir komuttur ve [[bir anahtar kelimedir: /ubuntu/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
[[ a < b ]]: sözlükbilimsel karşılaştırma[ a \< b ]: Yukarıdaki ile aynı. \veya başka herhangi bir komut için olduğu gibi yönlendirme yapar. Bash uzantısı.expr a \< b > /dev/null: POSIX eşdeğeri², bkz: Bash'ten küçük ya da eşit sözlükbilim dizeleri nasıl test edilir?&& ve ||
[[ a = a && b = b ]]: doğru, mantıklı ve[ a = a && b = b ]: sözdizimi hatası, &&AND komut ayırıcısı olarak ayrıştırıldıcmd1 && cmd2 [ a = a -a b = b ]: eşdeğer, ancak POSIX³ tarafından kullanımdan kaldırıldı[ a = a ] && [ b = b ]: POSIX ve güvenilir eşdeğeri(
[[ (a = a || a = b) && a = b ]]: yanlış[ ( a = a ) ]: sözdizimi hatası, ()alt kabuk olarak yorumlanır[ \( a = a -o a = b \) -a a = b ]: eşdeğer, ancak ()POSIX tarafından kullanımdan kaldırıldı{ [ a = a ] || [ a = b ]; } && [ a = b ]POSIX eşdeğeri 5sözcük bölme ve genişletmeler üzerine dosya adı oluşturma (split + glob)
x='a b'; [[ $x = 'a b' ]]: true, tırnak işaretleri gerekmezx='a b'; [ $x = 'a b' ]: sözdizimi hatası, [ a b = 'a b' ]x='*'; [ $x = 'a b' ]: geçerli dizinde birden fazla dosya varsa sözdizimi hatası.x='a b'; [ "$x" = 'a b' ]: POSIX eşdeğeri=
[[ ab = a? ]]: doğru, çünkü desen eşleşmesi yapıyor ( * ? [sihir). Geçerli dizindeki dosyalara genişlemez.[ ab = a? ]: a?glob genişler. Bu nedenle, geçerli dizindeki dosyalara bağlı olarak doğru veya yanlış olabilir.[ ab = a\? ]: yanlış, glob genişlemesi değil=ve ==her ikisi de aynıdır [ve [[ancak ==bir Bash uzantısıdır.case ab in (a?) echo match; esac: POSIX eşdeğeri[[ ab =~ 'ab?' ]]: yanlış 4 , ile büyü kaybeder''[[ ab? =~ 'ab?' ]]: doğru=~
[[ ab =~ ab? ]]: doğru, POSIX genişletilmiş düzenli ifade eşleşmesi, ?genişlemeyi engellemez[ a =~ a ]: sözdizimi hatası. Bash eşdeğeri yok.printf 'ab\n' | grep -Eq 'ab?': POSIX eşdeğeri (yalnızca tek satırlı veriler)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?': POSIX eşdeğeri.Tavsiye : her zaman kullanın [].
[[ ]]Gördüğüm her yapı için POSIX eşdeğeri var .
Sizi kullanırsanız [[ ]]:
[garip bir isimle düzenli bir emirdir, özel anlambilim söz konusu değildir.Orn [[...]]Korn kabuğundaki eşdeğer yapıdan esinlenmiştir
² ancak bazı değerler için başarısız aveya b(gibi +ya index) ve sayısal karşılaştırma eğer yapar ave bgöz gibi ondalık tamsayılar. expr "x$a" '<' "x$b"her ikisi de etrafında çalışır.
³ ve ayrıca bazı değerleri için başarısız aveya bbenzeri !veya (.
Bash 3.2 ve üzeri 4 ve bash 3.1 ile uyumluluk sağlanmamıştır (ile olduğu gibi BASH_COMPAT=3.1)
5 ve (burada {...;}yerine (...)gereksiz bir alt kabuk çalıştıracak olan komut grubu ile birlikte) gruplama gerekli değildir ||ve &&kabuk işleçleri ( ||ve && [[...]]işleçlerin veya -o/ -a [işleçlerin aksine ) eşit önceliğe sahiptir. Yani [ a = a ] || [ a = b ] && [ a = b ]eşdeğer olur.
[]benim tercihim olarak okunmalıdır : []taşınabilirliği kaybetmek istemiyorsanız kullanın . Belirtildiği gibi burada : POSIX veya BourneShell için taşınabilirlik / uygunluk bir sorun olacaksa, eski sözdizimi kullanılmalıdır. Diğer yandan komut dosyası BASH, Zsh veya KornShell gerektiriyorsa, yeni sözdizimi genellikle daha esnektir, ancak geriye dönük olarak uyumlu olmayabilir. [[ ab =~ ab? ]]Yapabileceğim ve geriye dönük uyumluluktan daha fazla endişe etmiyorsam tercih ederimprintf 'ab' | grep -Eq 'ab?'
Durum testi için tekli parantez içinde (yani [...]), single gibi bazı operatörler =tüm kabuklar tarafından desteklenirken, operatörün kullanımı ==eski kabukların bazıları tarafından desteklenmez.
Durumu deneyinde (yani [[...]]) için çift parantez içinde, kullanarak arasında hiçbir fark yoktur =ya da ==yeni ya da eski kabuklar.
Düzenleme: Ayrıca şunu da not etmeliyim: Bash'da, her zaman çift parantez [[...]] kullanın, çünkü tek parantezden daha güvenlidir. Nedenini aşağıdaki örnekle açıklayacağım:
if [ $var == "hello" ]; then
$ var boş / boş olursa, betiğin gördüğü budur:
if [ == "hello" ]; then
hangi senaryonuzu kıracak. Çözüm ya çift parantez kullanmak ya da değişkenlerinizin ( "$var") etrafına tırnak işaretleri koymayı unutmayın . Çift parantez daha iyi savunma kodlama uygulamasıdır.
[[, [komuta benzer (ancak bundan daha güçlü) bir bash anahtar kelimesidir .
Görmek
http://mywiki.wooledge.org/BashFAQ/031 ve http://mywiki.wooledge.org/BashGuide/TestsAndDurumlar
POSIX sh için yazmıyorsanız, öneririz [[.
ışık normal ifadesi eşleşmesi için çift köşeli parantezleri kullanabilirsiniz, örneğin:
if [[ $1 =~ "foo.*bar" ]] ; then
(Kullandığınız bash sürümü bu sözdizimini desteklediği sürece)
Bash kılavuzu diyor:
[[İle kullanıldığında, '<' ve '>' operatörleri geçerli yerel ayarı kullanarak sözlükbilimsel olarak sıralar. Test komutu ASCII sıralamasını kullanır.
(Test komutu [] ile aynıdır)