komut dosyasında $ {} ve $ () arasındaki fark


28
$ echo $(date)
Thu Jul 2 16:33:11 SGT 2015
$ echo ${date}

$ name=foo
$ echo $(name)
ksh: name:  not found

$ echo ${name}
foo

$ {Değişken} gibi görünüyor, $ değişkeniyle aynıdır. $ () ise bir komutu çalıştırmak içindir. O zaman neden $ {} kullanmalı?


Yanıtlar:


39

$(command)"komut değiştirme" dir. Anladığınız gibi, çalışır, commandçıktısını alır ve bunu içeren komut satırına ekler $(…); Örneğin,

$ ls -ld $(date +%B).txt
-rwxr-xr-x  1 Noob Noob    867 Jul  2 11:09 July.txt

${parameter}"parametre değiştirme" dir. Kabuğun man sayfasında bash (1)Parametre Genişletme ” başlığı altında birçok bilgi bulunabilir :

${parameter}
    Değeri parametresi ikame edilir. Ayraçları zaman gerekli olan bir parametre , birden fazla rakam ile konumsal bir parametredir, veya parametre değildir isminin bir parçası olarak yorumlanmamalıdır bir karakter gelir.

Konumsal parametreler için aşağıdaki “ Konumsal Parametreler ” bölümüne bakın. En yaygın kullanımında, diğer cevaplarda gösterildiği gibi, parameterdeğişken bir addır. ${…}Form, yukarıda paragrafın sonunda belirtildiği gibi, sen (yani bir değişkenin değerini almak sağlar ) ve bir harf, rakam veya alt çizgi ile hemen izleyin:$variable_name

$ hayvan = kedi
$ echo $ hayvanlar
                                # “Hayvanlar” gibi bir değişken yok .
$ echo $ {hayvan} s
kediler
$ echo $ animal_food
                                # “Animal_food” gibi bir değişken yok .
$ echo $ {animal} _food
kedi maması

Bunu tırnak işaretleri ile de yapabilirsiniz:

$ echo "$ hayvan" lar
kediler

Veya, seçeneklerde bir alıştırma olarak, ikinci bir değişkeni kullanabilirsiniz:

$ çoğul = s
$ echo $ hayvan $ çoğul
kediler

Ancak bu sadece 1. adımdır. Man sayfasındaki bir sonraki paragraf biraz ilginç olsa da ilginçtir:

Parametrenin ilk karakteri bir ünlem ise ( !) ise, değişken bir yönelim seviyesi verilir. Bash, parametrenin geri kalanından oluşan değişkenin değerini değişkenin adı olarak kullanır; bu değişken daha sonra genişletilir ve bu değer, değişimin geri kalanında, parametrenin kendisinin değeri yerine kullanılır . Bu dolaylı genişleme olarak bilinir .     (İstisnalar)    Ünlem işareti, dolaylı olarak tanıtmak için hemen soldaki ayracı izlemelidir.

Örnek olarak bu durumu nasıl daha açık hale getirebileceğimden emin değilim:

$ hayvan = kedi
$ echo $ hayvan
kedi
$ cat = tekir
$ echo $ cat
tekir
$ echo $ {! animal}
tekir                            # Eğer $ hayvan olan “kedi” , sonra {! hayvansal} $ olan $ kedi yani, “tekir”

Öyleyse bu adıma 1½ diyelim. 2. adım olarak yapabileceğiniz birçok ilginç şey var:

$ hayvan = kedi
$ echo $ {# hayvan}
3                                # Dize uzunluğu
$ echo $ {hayvan / at / ow}
inek                              # Değiştirme

Sen olmadan bunların hiçbirini yapamaz {... }parantezler.

Konumlandırma parametreleri

Bu yapay örneği ele alalım:

$ cat Instagram Hesabındaki Resim ve Videoları myecho.sh
echo $ 1 $ 2 $ 3 $ 4 $ 5 $ 6 $ 7 $ 8 $ 9 $ 10 $ 11 $ 12 $ 13 $ 14 $ 15
$ ./myecho.sh Hey kepçe çukuru, Kedi ve keman, İnek ayın üstünden atladı.
Hey Kepçe, Kedi ve Keman Hey0 Hey1 Hey2 Hey3 Hey4 Hey5

Kabuk anlamıyor çünkü $10, $11, vb davranır $10o sanki ${1}0. Ancak man sayfasında da belirtildiği gibi anlamlandırır ${10}, ${11}(“birden fazla rakam içeren pozisyonel bir parametre”).

Fakat aslında böyle senaryolar yazmayın; Uzun argüman listeleri ile başa çıkmak için daha iyi yollar var.

Yukarıdakiler (daha birçok konstrüksiyon formuyla birlikte ) kabuğun man sayfasında bash (1) ' de daha büyük bir uzunlukta tartışılmaktadır .${parameter…something_else}

Alıntılar Üzerine Bir Not

Yapmamak için iyi bir nedeniniz yoksa ve ne yaptığınızı bildiğinizden emin olmadığınız sürece, kabuk değişkenlerini her zaman alıntı yapmanız gerektiğini unutmayın . Aksine, diş telleri önemli olabilirken, tırnak işaretleri kadar önemli değillerdir.

$ dosyaadı = "kreş rhyme.txt"
$ ls -ld $ {dosyaadı}
ls: Çocuk odasına erişemiyor: Böyle bir dosya ya da dizin yok
ls: rhyme.txt dosyasına erişemiyor: böyle bir dosya veya dizin yok
$ ls -ld "$ dosyaadı"
-rwxr-xr-x 1 Noob Noob 5309 2 Temmuz 11:09 kreş kafiye.txt

Bu aynı zamanda konumsal parametreler için de geçerlidir (yani, komut satırı argümanları; örneğin, "$1") ve ayrıca komut değiştirme:

$ ls -ld $ (tarih "+% B% Y") .txt
ls: temmuza erişemiyor: böyle bir dosya veya dizin yok
ls: 2015.txt dosyasına erişemiyor: böyle bir dosya veya dizin yok
$ ls -ld "$ (tarih" +% B% Y "). txt"
-rwxr-xr-x 1 Noob Noob 687 2 Temmuz 11:09 Temmuz 2015.txt

Bkz Bash tırnak komut ikamesi üzerinde çıkışsız tırnak arasındaki etkileşime kısa risale için $(... ).


harika örnek için teşekkürler. Kullanımını detaylandırır mısın! senin örneğinde. Nasıl çalıştığını gerçekten anlamıyorum.
Noob

@ Nooob: Tamam, kullanımı üzerinde durdum !.
G-Man,

Teşekkürler. Her nasılsa, hayvan aslında cat değeri yerine kedi değişkenine atıfta bulunuyor. Aynı zamanda $ {animal / at / ow} 'ta / c' nin nasıl "c" haline geldiğini de bana söyleyebilir misiniz? anlaşılması zor.
Noob,

ayrıca, bu cümleyi iyi anlatabilir misin - "$ {parametre} Parametrenin değeri değiştirildi." ne ile değiştirildi? parametre meyve ise ve değeri elma - meyve = elma ise, $ {meyve} - elmanın yerine? gerçekten burada yerine geçen anlamını anlama
Noob

@ Nooob: “ ${!animal}aslında $catcat değeri yerine değişkene atıfta bulunuyor .” Evet, bu tam olarak mesele. “$ {Animal / at / ow} 'ta / at nasıl" c "olur?” Huh? / at "c" olmaz; “Cat”, “at” yerine “ow” ile değiştirildiğinde “inek” olur.
G-Man,

7

Örnekte, $ var ve $ {var} aynıdır. Bununla birlikte, küme parantezleri değişkeni bir dizgede genişletmek istediğinizde kullanışlıdır:

    $ string=foo
    $ echo ${string}bar
      foobar
    $ echo $stringbar

    $ 

Bu nedenle, küme parantezleri, kendisinin ikame edileceği yeni değişkenin adını almak için değişkeni ikame etmek için bir araç sağlar.


4

Genellikle dizelerde daha sık görüyorum. Böyle bir şey işe yaramaz:

var="a"
echo "$varRAW_STRING"

Ama bu olacak:

var="a"
echo "${var}RAW_STRING"

Doğru söylediğiniz gibi, $()bir komutu çalıştırmak için kullanılır:

dir_contents=$(ls)

Ayrıca geri tepme çubukları da kullanabilirsiniz, ama ben $()daha çok yönlü buluyorum . Birincisi, backticks (kolayca) iç içe olamaz.

date_directory=`ls `date '+%Y-%m-%d'`` # Makes no sense
date_directory=$(ls $(date '+%Y-%m-%d')) # Much better

Aslında backticks yapabilirsiniz iç içe olmak: date_directory=`ls \`date '+%Y-%m-%d'\``. Ama çok çirkin; $(…)çok daha net ve kullanımı kolaydır.
G-Man 'Reinstate Monica' Dedi

Tamam, yeterince adil. Bu teknik olarak mümkündür, ama hiç kimse sırf okunabilirliği yapıyor düşünemiyorum
bytesized

1
Eh, `…`oldu önce yıllarca komut ikamesi için (yalnızca) sözdizimi icat edilmiştir şey hayal etmek gerek kalmaz, - insanlar bunu yaptı. $(…)
G-Man 'Reinstate Monica' Dedi

s / ever yapıyor / artık yapıyor /
bytesized
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.