Tam olarak aradaki farkın ne olduğunu merak ettim.
[[ $STRING != foo ]]
ve
[ $STRING != foo ]
Bunun dışında, ikincisi posix uyumludur, sh'de bulunur ve birincisi bash'ta bulunan bir uzantıdır.
Tam olarak aradaki farkın ne olduğunu merak ettim.
[[ $STRING != foo ]]
ve
[ $STRING != foo ]
Bunun dışında, ikincisi posix uyumludur, sh'de bulunur ve birincisi bash'ta bulunan bir uzantıdır.
Yanıtlar:
Birkaç fark var. Bence en önemlilerinden bazıları:
[
Bash ve diğer birçok modern kabuğunda yerleşiktir. Yerleşik bir kapanış gerekliliği ile [
benzerdir . Komutlar geriye dönük olarak uyumlu olacak şekilde yerleşikler ve işlevselliklerini ve sınırlamaları ile birlikte bunları taklit ederler . Orijinal yürütülebilir dosyalar halen POSIX uyumluluğu ve geriye dönük uyumluluk için hala mevcuttur. Komutu Bash'de çalıştırmak, bunun varsayılan olarak yerleşik olarak yorumlandığını gösterir . (Not: yalnızca PATH üzerindeki yürütülebilir dosyaları arar ve buna eşittir )test
]
[
test
/bin/[
/bin/test
type [
[
which [
type -p [
[[
o kadar uyumlu değil, mutlaka neye /bin/sh
işaret ettiği ile çalışmak olmaz . Yani [[
daha modern Bash / Zsh / Ksh seçeneğidir.[[
Kabukta yerleşik olduğundan ve eski gerekliliklere sahip olmadığından, boşluklu bir dizeye değer veren değişkenleri karıştırmak için IFS değişkenine dayalı kelime bölme konusunda endişelenmenize gerek yoktur . Bu nedenle, değişkeni çift tırnak içine almanıza gerek yoktur.Çoğunlukla, geri kalanı sadece daha hoş bir sözdizimidir. Daha fazla fark görmek için bu bağlantıyı bir SSS cevabına tavsiye ediyorum: Test, [ve [[?] Arasındaki fark nedir? . Aslında bash komut dosyası yazma konusunda ciddiysen , SSS, Tuzaklar ve Rehber dahil tüm wikileri okumanı öneririm . Kılavuz bölümündeki test bölümü de bu farklılıkları açıklar ve taşınabilir olmaktan endişe duymanıza gerek kalmıyorsa neden yazarların daha iyi bir seçim olduğunu düşünüyor . Ana nedenler:[[
< >
Girdi yönlendirme olarak değerlendirilmemeleri için ters eğik çizgilere göre daha az ve daha fazla kaçmanız gerekmez , bu da dosyaların üzerine yazarak bazı şeyleri gerçekten karıştırabilir. Bu yine [[
bir yerleşik olmak için geri gider . [(Test) harici bir programsa, kabuğun değerlendirdiği şekilde bir istisna yapması gerekir <
ve >
sadece /bin/test
çağrılırsa, bu gerçekten mantıklı olmaz.Kısacası:
[bir bash yerleşiktir
[[]] bash Anahtar Kelimeler
Anahtar Kelimeler: Anahtar kelimeler yerleşik yapılara benzer, ancak temel fark, özel ayrıştırma kurallarının kendileri için geçerli olmasıdır. Örneğin, [bir bash yerleşimidir, [[bir bash anahtar sözcüğüdür). Her ikisi de malzeme testi için kullanılır, ancak [[bir yerleşik değil, bir anahtar kelime olduğundan, onu çok kolaylaştıran birkaç özel ayrıştırma kuralından yararlanır:
$ [ a < b ]
-bash: b: No such file or directory
$ [[ a < b ]]
İlk örnek bir hata verir çünkü bash b dosyasını [a] komutuna yönlendirmeye çalışır. İkinci örnek aslında beklediğiniz şeyi yapar. <Karakterinin artık Dosya Yönlendirme işlecinin özel bir anlamı yoktur.
Kaynak: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments
[
bir POSIX kabuk komutu; yerleşik olması gerekmiyor. ]
sadece bu komutun aradığı bir argümandır, böylece sözdizimi dengelenir. Komut, bunun bir kapanış aramaması test
dışında eşanlamlıdır . test
]
Davranış farklılıkları
Bash 4.3.11'deki bazı farklılıklar:
POSIX vs Bash uzantısı:
Düzenli emir vs büyü
[
garip bir isimle sadece düzenli bir komuttur.
]
sadece [
daha fazla argümanın kullanılmasını önleyen bir argümandır .
Ubuntu 16.04 aslında /usr/bin/[
coreutils tarafından sağlananlar için çalıştırılabilir bir dosyaya sahip ancak bash yerleşik sürümü öncelikli.
Hiçbir şey Bash'in emri ayrıştırdığı şekilde değişmez.
Özellikle, <
yönlendirme &&
ve ||
birden çok komutu birleştirmek, ( )
kaçmadıkça alt kabuklar oluşturur \
ve sözcük genişletme her zamanki gibi olur.
[[ 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 dilinde: [
yerleşik bir komuttur ve [[
bir anahtar kelimedir: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
[[ a < b ]]
: sözlük bilgisi karşılaştırması[ a \< b ]
: Yukarıdaki ile aynı. \
gerekli 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ğer², bkz: https://stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in-bash/52707989#52707989&&
ve ||
[[ a = a && b = b ]]
: doğru, mantıklı ve[ a = a && b = b ]
: &&
bir AND komut ayırıcı olarak ayrıştırılan sözdizimi hatasıcmd1 && cmd2
[ a = a -a b = b ]
: eşdeğer, ancak POSIX tarafından onaylanmadı.[ 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 5genişlemelerde sözcük bölme ve dosya adı oluşturma (split + glob)
x='a b'; [[ $x = 'a b' ]]
: true, tırnak gerekli değilx='a b'; [ $x = 'a b' ]
: sözdizimi hatası, genişler [ 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? ]]
: true, çünkü desen eşleşmesi yapıyor ( * ? [
sihir). Glob, 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\? ]
: false, 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 , sihirini kaybeder''
[[ ab? =~ 'ab?' ]]
: doğru=~
[[ ab =~ ab? ]]
: true, POSIX düzenli ifade eşleşmesini ?
genişletti , genişlemiyor[ 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.Öneri : daima kullanın []
.
[[ ]]
Gördüğüm her yapı için POSIX eşdeğeri var .
Eğer seni kullanırsan [[ ]]
:
[
garip bir isimle sadece düzenli bir komuttur, özel bir anlambilim söz konusu değildir.[[...]]
Korn kabuğundaki eşdeğer yapıdan esinlenmiştir
² ama bazı değerler için başarısız a
veya b
(gibi +
ya index
) ve eğer sayısal bir karşılaştırma yapar a
ve b
ondalık tamsayılar benziyor. expr "x$a" '<' "x$b"
her ikisi de çalışır.
³ ve ayrıca a
veya b
benzeri !
veya bazı değerleri için başarısız olur (
.
4 Bash 3.2 ve yukarıda ve 3.1 vurmayı sağlanan uyumluluk (olduğu gibi etkin değildir BASH_COMPAT=3.1
)
5 ( gereksiz bir alt kabuk çalıştıracak olan {...;}
komut grubu ile burada) gruplama (...)
gerekli değildir ||
ve &&
kabuk operatörleri ( ||
ve &&
[[...]]
operatörler veya -o
/ -a
[
operatörler aksine ) eşit önceliğe sahip olduğundan gerekli değildir. Yani [ a = a ] || [ a = b ] && [ a = b ]
eşdeğer olurdu.
printf 'ab' | grep -Eq 'ab?'
içinde if [ … ]
?
if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi
. []
tıpkı bunun gibi bir komuttur grep
. Bu ()
komutta gerekli olmayabilir, emin değilim: Çünkü, |
Bash'in nasıl ayrıştırdığına bağlı olarak ekledim . Eğer hayır |
olmasaydı sadece yazabileceğinden eminim if cmd arg arg; then
.
()
gibi görünüyor: stackoverflow.com/questions/8965509/…
Tek Braket, yani []
şartlı bir ifadeyi içine almak için uyumlu POSIX kabuğudur.
İkili Parantez, yani [[]]
standart POSIX versiyonunun geliştirilmiş (veya genişletme) bir versiyonudur, bu bash ve diğer kabuklar (zsh, ksh) tarafından desteklenir.
Bash olarak, kullandığımız sayısal karşılaştırma için eq
, ne
, lt
ve gt
karşılaştırma için çift parantez ile kullanabileceğimiz ==
, !=
, <,
ve >
tam anlamıyla.
[
, test komutunun eş anlamlısıdır. Kabuğun içine yerleştirilse bile yeni bir işlem yaratır.[[
bir program değil, bir anahtar kelime olan yeni bir geliştirilmiş sürümüdür. Örneğin:
[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works
if
ifade bağlamında , bkz. Mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D