Bash kodunuzu ayrıştırma biçiminde, bir dahili anahtar ile bir anahtar kelime arasında güçlü bir fark var. Farkdan bahsetmeden önce, tüm anahtar kelimeleri ve yerleşikleri listeleyelim:
Yerleşikleri:
$ compgen -b
. : [ alias bg bind break
builtin caller cd command compgen complete compopt
continue declare dirs disown echo enable eval
exec exit export false fc fg getopts
hash help history jobs kill let local
logout mapfile popd printf pushd pwd read
readarray readonly return set shift shopt source
suspend test times trap true type typeset
ulimit umask unalias unset wait
Anahtar Kelimeler:
$ compgen -k
if then else elif fi case
esac for select while until do
done in function time { }
! [[ ]] coproc
Örneğin, [
öğesinin yerleşik olduğunu ve [[
'nin bir anahtar kelime olduğunu unutmayın. Bu farkı, iyi bilinen operatörler olduklarından, aşağıdaki farkı gösterecek şekilde kullanacağım: herkes bunları biliyor ve düzenli olarak kullanıyor (veya yapmalı).
Bir anahtar kelime Bash tarafından ayrıştırılmakta çok erken bir zamanda taranır ve anlaşılır. Bu, örneğin aşağıdakilere izin verir:
string_with_spaces='some spaces here'
if [[ -n $string_with_spaces ]]; then
echo "The string is non-empty"
fi
Bu iyi çalışıyor ve Bash mutlu bir şekilde çıkacak
The string is non-empty
$string_with_spaces
alıntı yapmadığımı unutmayın. Oysa şu:
string_with_spaces='some spaces here'
if [ -n $string_with_spaces ]; then
echo "The string is non-empty"
fi
, Bash'in mutlu olmadığını gösterir:
bash: [: too many arguments
Neden dahili anahtarlarla değil, anahtar kelimelerle çalışır? Bash kodu ayrıştırdığı zaman, anahtar kelime olan [[
değerini görür ve bunun çok özel olduğunu anlar. Böylece ]]
kapanışını arayacak ve içeriye özel bir şekilde davranacaktır. Bir yerleşik (veya komut) argümanlarla çağrılacak gerçek bir komut olarak kabul edilir. Bu son örnekte, bash [
komutunu argümanlarla çalıştırması gerektiğini (satır başına bir tane gösterilmiştir):
-n
some
spaces
here
]
Değişken genişleme, alıntı kaldırma, yol adı genişletme ve kelime bölme gerçekleştiği için. % Co_de% komutunun kabukta oluşturulduğu ortaya çıkar, dolayısıyla bu argümanlar ile yürütülür, bu da bir hatayla sonuçlanır, dolayısıyla şikayetle sonuçlanır.
Pratikte, bu ayrımın karmaşık davranışlara izin verdiğini görüyorsunuz; bu, yerleşiklerle (veya komutlarla) mümkün olmayacaktır.
Yine de pratikte, bir yerleşimi bir anahtar kelimeden nasıl ayırt edebilirsiniz? Bu gerçekleştirmek için eğlenceli bir deney:
$ a='['
$ $a -d . ]
$ echo $?
0
Bash [
satırını ayrıştırdığında, özel bir şey (yani, takma adlar, yönlendirme yok, anahtar sözcük yok) görmez, bu nedenle yalnızca değişken genişleme gerçekleştirir. Değişken açılımlardan sonra şunu görür:
[ -d . ]
öyleyse $a -d . ]
, [
ve -d
argümanları ile .
komutunu çalıştırır (ki bu% s_de% 'nin bir dizin olup olmadığını test eder).
Şimdi bak:
$ a='[['
$ $a -d . ]]
bash: [[: command not found
Ah. Çünkü Bash bu çizgiyi gördüğü zaman, özel bir şey görmez ve dolayısıyla tüm değişkenleri genişletir ve sonunda görür:
[[ -d . ]]
Şu anda, takma uzantılar ve anahtar kelime taraması uzun süredir gerçekleştirildi ve artık gerçekleştirilmeyecek, bu nedenle Bash ]
adlı komutu bulmaya çalışıyor, bulamıyor ve şikayet ediyor.
Aynı satırlarda:
$ '[' -d . ]
$ echo $?
0
$ '[[' -d . ]]
bash: [[: command not found
ve
$ \[ -d . ]
$ echo $?
0
$ \[[ -d . ]]
bash: [[: command not found
Alias genişletme de oldukça özel bir şeydir. Hepiniz en az bir kez aşağıdakileri yaptınız:
$ alias ll='ls -l'
$ ll
.... <list of files in long format> ....
$ \ll
bash: ll: command not found
$ 'll'
bash: ll: command not found
Akıl yürütme aynıdır: takma genişletme ve alıntı kaldırma işleminden çok önce takma ad uzatma gerçekleşir.
Anahtar kelime v.s. Alias
Şimdi bir anahtar kelime olarak takma ad tanımlarızsa ne olacağını düşünüyorsunuz?
$ alias mytest='[['
$ mytest -d . ]]
$ echo $?
0
Oh, işe yarıyor! Bu yüzden takma adlar, anahtar kelimeleri taklit etmek için kullanılabilir! bilmek güzel.
Sonuç: yerleşimler gerçekten komutlar gibi davranırlar: doğrudan değişken genişleme ve kelime bölme ve sallanma süreçlerine maruz kalan argümanlarla yürütülen bir eyleme karşılık gelirler. Değişken genişleme, vb. Sonra verilen argümanlarla çağrılan .
veya [[
değerindeki bir yerde bir dış komut olması gibi bir şey. dediğimde, gerçekten de bir dış komut olması gibi. Ben sadece argümanlar, kelime bölme, globbing, değişken genişleme vb. Anlamındayım. Bir yerleşik, kabuğun dahili durumunu değiştirebilir!
Diğer taraftan, anahtar kelimeler taranır ve çok erken anlaşılır ve gelişmiş kabuk davranışı sağlar: Kabuk, kelime bölme veya yol adı genişletme, vb. yasaklayabilir.
Artık, yerleşik anahtar kelimelere ve anahtar kelimelere bakın ve neden bazılarının anahtar kelime olması gerektiğini anlamaya çalışın.
/bin
bir anahtar kelimedir. Davranışlarını bir işlevle taklit etmek mümkün görünüyor:
not() {
if "[email protected]"; then
return false
else
return true
fi
}
Ancak bu, aşağıdaki gibi yapıları yasaklayabilir:
$ ! ! true
$ echo $?
0
veya
$ ! { true; }
echo $?
1
/usr/bin
için aynı: Bir anahtar kelimeye sahip olmak daha karmaşıktır, böylece karmaşık bileşik komutları ve boru hatlarını yeniden yönlendirmelerle zamanlayabilirsiniz:
$ time grep '^#' ~/.bashrc | { i=0; while read -r; do printf '%4d %s\n' "$((++i))" "$REPLY"; done; } > bashrc_numbered 2>/dev/null
!
, sadece bir komut (hatta yerleşik) ise, yalnızca time
, time
ve grep
argümanlarını görecek, bunu zaman alacak ve daha sonra çıkışı boru hattının kalan kısımlarından geçecektir. . Ama bir anahtar kelime ile Bash her şeyi halledebilir! Yeniden yönlendirmeler de dahil olmak üzere, tüm boru hattının%% sini kullanabilir! % Co_de% salt bir komut ise, yapamadık:
$ time { printf 'hello '; echo world; }
Deneyin:
$ \time { printf 'hello '; echo world; }
bash: syntax error near unexpected token '}'
Düzeltmeyi deneyin (?):
$ \time { printf 'hello '; echo world;
time: cannot run {: No such file or directory
umutsuz.
Anahtar kelime ile takma ad mı?
$ alias mytime=time
$ alias myls=ls
$ mytime myls
Ne olduğunu düşünüyorsun?
Gerçekten, yerleşik komutta olduğu gibi bir kabuk gibidir, oysa bir anahtar kelime , karmaşık davranışlara izin veren bir şeydir! Kabuğun dilbilgisinin bir parçası olduğunu söyleyebiliriz.