Bize iki farklı sonuç veren iki çizgiyi ele alalım.
p=$(cd ~ && pwd) ; echo $p
p=$(cd ~ | pwd) ; echo $p
İkisi arasındaki fark nedir?
|kabuklarda çalıştırmanın her iki yanındaki komutlar .
Bize iki farklı sonuç veren iki çizgiyi ele alalım.
p=$(cd ~ && pwd) ; echo $p
p=$(cd ~ | pwd) ; echo $p
İkisi arasındaki fark nedir?
|kabuklarda çalıştırmanın her iki yanındaki komutlar .
Yanıtlar:
İçinde p=$(cd ~ && pwd):
Komut ikamesi,, $()bir alt kabukta çalışır
cd ~dizini ~(eviniz) olarak değiştirir, cdbaşarılı olursa ( &&) pwdSTDOUT'ta dizin adını yazdırır, dolayısıyla kaydedilen dize pana dizininiz olur;/home/foobar
İçinde p=$(cd ~ | pwd):
Yine $()bir subshell ortaya çıkarır
|İlgili alt kabuklarda her iki taraftaki komutlar (ve her ikisi de aynı anda başlar)
böylece cd ~bir kabuktaki yapılıyorsa ve pwdbir de ayrı alt kabuğa
yani sadece STDOUT'u pwdyani komutu çalıştırdığınız yerden alırsınız, bu hayal edebileceğiniz gibi herhangi bir dizin olabilir, bu nedenle pana dizininizi değil, komutun çağrıldığı dizinin adını içerecektir.
cd ~herhangi bir çıktı üretmez ve pwdherhangi bir girdi okumaz.
(cd ~);p=$(pwd)değil mi?
Temel sorun operatörlerin &&ve |iki komutu nasıl bağladıklarıdır.
&&Çıkış kodu aracılığıyla komutları bağlar. Bağlantı |, iki komutu dosya tanımlayıcıları (stdin, stdout) aracılığıyla bağlar.
Önce basitleştirelim. Ödevi kaldırabilir ve yazabiliriz:
echo $(cd ~ && pwd)
echo $(cd ~ | pwd)
Bunu analiz etmek için komut yürütme alt kabuğunu bile kaldırabiliriz:
$ cd ~ && pwd
$ cd ~ | pwd
Komutların yürütüldüğü dizini gösterme istemini değiştirirsek, şuna benzer PS1='\w\$ ':
/tmp/user$ cd ~ && pwd
/home/user
~$
cd ~, "mevcut dizini" komutu ( /home/user) çalıştıran gerçek kullanıcının evine değiştirdi .pwddeğerini değiştirdi .~~$Dizin değişikliği başarısız olursa (çıkış kodu 0 değil) (dizin mevcut değilse, izinler dizini okumayı engeller) bir sonraki komut yürütülmez.
Misal:
/tmp/user$ false && pwd
/tmp/user$ _
1 çıkış kodu bir falsesonraki komutun yürütülmesini engeller.
Bu nedenle, "komut 1" in çıkış kodu "komut 2" yi etkileyen şeydir.
Şimdi, tüm komutun etkileri:
/tmp/user$ echo $(cd ~ && pwd)
/home/user
/tmp/user$ _
Dizin değiştirildi, ancak bir alt kabuğun içinde $(…), değiştirilen dizin yazdırılır /home/user, ancak alt kabuk kapandığında hemen atılır. Pwd ilk dizin ( /tmp/user) olarak döner .
Olan şey budur:
/tmp/user$ cd ~ | pwd
/tmp/user
/tmp/user$ _
Meta karakter |(gerçek bir operatör değil) kabuğu "Boru" olarak adlandırılan şeyi oluşturmak için işaret eder, borunun ( |) her iki tarafındaki her komut , önce sağ taraf olan her bir alt kabuğun içine ayarlanır sonra soldaki komut. /dev/stdinSağ komutun giriş dosyası tanımlayıcısı ( ), çıkış tanımlayıcısına ( /dev/stdout) bağlanır ve ardından her iki komut da etkileşime girecek şekilde başlatılıp bırakılır. Sol komutun ( cd -) çıkışı yoktur ve ayrıca sağ komut ( pwd) giriş kabul etmez. Yani, her biri kendi alt kabuğunun içinde bağımsız olarak çalışır.
cd ~Bir kabuğun PWD değiştirir.pwdDiğer alt kabuğun (tamamen bağımsız) basar.Her kabuk üzerindeki değişiklikler boru sona erdiğinde atılır, harici alt kabuk pwd'yi değiştirmez.
Bu nedenle iki komut yalnızca "dosya tanımlayıcıları" ile bağlanır.
Bu durumda gönderilen bir şey yoktur ve hiçbir şey okunmaz.
Bütün komut:
$ echo "$(cd ~ | pwd)"
Sadece komutun yürütüldüğü dizini yazdırır.
'|' Demek istediğinden emin değilim veya '||' ikinci durumda.
'|' kabukta bir komutun çıktısını diğerinin girişine bağlar - ortak kullanım durumu şudur:
curl http://abcd.com/efgh | grep ijkl
yani bir komut çalıştırmak ve bir komutun çıktısını işlemek için başka bir komut kullanmak.
Verdiğiniz örnekte, 'cd' tipik olarak herhangi bir çıktı üretmediği ve 'pwd' herhangi bir girdi beklemediğinden oldukça saçmadır.
'&&' ve '||' ortak komutlarıdır. Çoğu dilde mantıksal "ve" ve "veya" operatörleriyle aynı şekilde kullanılmak üzere tasarlanmıştır. Ancak yapılan optimizasyonlar onlara kabuk programlama paradigması olan belirli bir davranış kazandırır.
Mantıksal bir "ve" işleminin sonucunu belirlemek için, yalnızca ilk koşul başarılı olursa ikinci koşulu değerlendirmeniz gerekir - ilk koşul başarısız olursa, genel sonuç her zaman yanlış olur.
Mantıksal bir "veya" işleminin sonucunu belirlemek için, yalnızca ilk koşul başarısız olursa ikinci koşulu değerlendirmeniz gerekir - ilk koşul başarılı olursa, genel sonuç her zaman doğru olur.
Bu nedenle, kabukta, başarılı bir sonuç kodu tamamlandığında ve döndüğünde command1 && command2 command2çalıştırılacaksanız command1. Eğer tamamlanırsa command1 || command2 command2çalıştırılacaksanız bir hata kodu döndürürse.command1command1
Bir diğer yaygın paradigma, command1bir test komutu olmaktır - bu, eğer / then deyimi olduğunda tek bir satır oluşturur - örneğin:
[ "$VAR" = "" ] && VAR="Value if empty"
O anda boşsa bir değişkene değer atamanın (uzun soluklu) bir yoludur.
Bu işlemin Stack Exchange'de başka bir yerde kullanılmasına ilişkin birçok örnek vardır