Hakkında bash örnekleri okuyorum if
ama 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 if
ama 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 -o
ve 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/bash
veya #!/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 ]]
X
sihirli 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 a
veya b
(gibi +
ya index
) ve sayısal karşılaştırma eğer yapar a
ve b
gö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 a
veya b
benzeri !
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)