Kabuktaki $ @ veri yapısı nedir?


13

Genellikle $@0 $ dışındaki tüm argümanları temsil etmek için kullanırız . Ancak, veri yapısının ne olduğunu bilmiyorum $@.

Neden $*çift ​​tırnak içine alındığında farklı davranıyor , kimse bana tercüman düzeyinde bir açıklama verebilir mi?

Döngü için yinelenebilir, bu yüzden dizi gibi görünüyor. Bununla birlikte, echo $@bir dizi ise, sadece ilk eleman gösterilecek, tamamen basit ile yankılanabilir . Kabuğun sınırlaması nedeniyle, yürütmek için daha fazla deneme kodu yazamıyorum.

Bu yazı arasındaki fark : Bu yazı nasıl $@farklı davrandığını gösterir $*. Ama veri türünü merak ediyorum $@. Bir yorumlama dili olan Shell, Python gibi, bir dizi temel türe göre verileri temsil etmelidir. Başka bir deyişle, $ @ 'ın bilgisayar belleğinde nasıl saklandığını bilmek istiyorum.

Bu bir dize, çok satırlı bir dize mi yoksa bir dizi mi?

Benzersiz bir veri türüyse, bu değişkenin bir örneği olarak özel bir değişken tanımlamak mümkün müdür?



@Haxiel, sanmıyorum, farklarını yazımın altına yazdım.
davmos

printf '%s\n' "$@"Ve ile çıktıdaki farkı test ederek daha iyi hizmet alabilirsiniz printf '%s\n' "$*". Yardımcı echoprogram, bir veya daha fazla olmalarına bakılmaksızın argümanlarını çıkarır. Her ikisi de (dizgiden oluşan) dizilerdir, ancak çift tırnak içine alındığında farklı davranırlar. İkisinden biri çok satırlı bir dize olsaydı, çok satırlı dizeleri (yapabilecekleri) depolayamazlardı. Hangi sorunu çözmeye çalıştığınız belli değil.
Kusalananda

2
Sorunuz, bir @vardeğişkenin temel depolaması açısından Perl'de ne olduğunu sormaya eşdeğerdir . Sıradan bir Perl programının nokta görünümünden, bir dizi / liste olarak erişilebilir olması (ve bir listenin beklendiği bağlamlar olması) önemli değildir.
Kusalananda

Yanıtlar:


16

Bourne kabuğunda bir hack olarak başladı. Bourne kabuğunda, liste bağlamında (komut satırı bağımsız değişkenleri veya fordöngülerin döngü yaptığı sözcükler) tüm sözcüklerde IFS sözcük bölünmesi (belirteçlemeden sonra ) yapıldı. Olsaydı:

IFS=i var=file2.txt
edit file.txt $var

İkinci satır 3 deyişle tokenised olacağını, $vargenişletileceğini bildirdi ve çalıştırmakta sona ereceğini böylece bölünmüş + gıdım bile, her üç kelime bitmiş olacaktır edile t, f, le.txt, f, le2.txtargüman olarak.

Bunun bazı bölümlerinden alıntı yapmak, bölünmüş küreyi önleyecektir. Bourne kabuğu başlangıçta hangi karakterlerin alıntılandığını 8'inci dahili olarak ayarlayarak hatırladı (Unix 8 bit temizlendiğinde daha sonra değişti, ancak kabuk hala hangi baytın alıntılandığını hatırlamaya benzer bir şey yaptı).

Her ikisi de $*ve $@konumsal parametrelerin aradaki boşlukla birleşmesiydi. Ancak $@çift ​​tırnak içine alındığında özel bir işlem gerçekleştirildi . Eğer $1içerdiği foo barve $2içerdiği baz, "$@"genişler:

foo bar baz
^^^^^^^ ^^^

( ^yukarıdaki s karakterlerden hangisinin 8. bitin ayarlandığını gösterir). Birinci boşluğun alıntılandığı (8. bitin ayarlandığı) ancak ikincisinin (aradaki sözcükler arasına eklenen) değil.

Ve bağımsız değişkenleri ayırmaya özen gösteren IFS bölünmesi (boşluk karakterinin $IFSvarsayılan olarak olduğu varsayılır). Bu $*, selefi Mashey kabuğunda (Bourson kabuğu sıfırdan yazılırken Thomson kabuğuna dayanarak) nasıl genişletildiğine benzer .

Bu, Bourne kabuğunda, başlangıçta "$@"konumsal parametreler listesi boşken (onunla çalışmak zorunda kaldınız) hiçbir şey yerine boş dizeye neden genişleyeceğini ${1+"$@"}, neden boş konum parametrelerini "$@"saklamadığını ve neden yapmadığını açıklar $IFSboşluk karakteri içermediğinde çalışmaz .

Amaç, bağımsız değişkenler listesini başka bir komuta aynen aktarabilmektir, ancak bu boş liste, boş öğeler veya $IFSboşluk içermediğinde düzgün çalışmadı (ilk iki sorun sonunda sonraki sürümlerde düzeltildi ).

Korn kabuğu (POSIX spesifikasyonunun dayandığı) bu davranışı birkaç şekilde değiştirdi:

  • IFS bölme işlemi yalnızca alıntılanmamış genişletmelerin sonucu olarak yapılır ( yukarıdaki örnekte olduğu gibi editveya file.txtyukarıdaki örnekte değil)
  • $*ve bir alıntı için , bu birleştiricinin Bourne kabuğundaki gibi tırnaksız olması ve boş olduğunda bir alıntı için , konum parametrelerinin ayırıcı olmadan eklenmesi dışında, boş olduğunda $@ilk karakteri $IFSveya boşluğu ile birleştirilir .$IFS"$@""$*"IFS
  • diziler için destek ekledi ve ${array[@]} ${array[*]}Bourne'yi andıran $*ve $@ancak 1 yerine 0 indeksinden başlayarak ve seyrek (daha çok ilişkisel diziler gibi) anlamına geliyor $@, yani gerçekten bir ksh dizisi olarak ele alınamaz ( csh/ rc/ zsh/ fish/ yashnerede $argv/ $*normal ile karşılaştırılamaz) dizileri).
  • Boş elemanlar korunur.
  • "$@"$#0 olduğunda artık boş dize yerine hiçbir şeye genişletilmez, boş olmadığı zaman boşluk içermediğinde "$@"çalışır . Joker karakter içermeyen bir sıralanmamış , boş olduğunda (konumsal parametrelerin boşlukla birleştirildiği) bir argümana genişler .$IFSIFS$*$IFS

ksh93 yukarıdaki kalan birkaç sorunu düzeltti. Ksh93'te $*ve $@konum parametrelerinin listesine genişler, değerinden bağımsız olarak ayrılır $IFSve daha sonra bölünmüş + globbed + brace-genişletilmiş, liste bağlamlarında, $*ilk bayt (karakter değil) ile birlikte $IFS, "$@"liste bağlamlarında listeye genişler değeri ne olursa olsun, konumsal parametrelerin $IFS. Liste dışı bağlamda, in gibi var=$@, $@değerine bakılmaksızın alanı ile birleştirilir $IFS.

bashdizileri ksh olanlardan sonra tasarlanmıştır. Farklılıklar:

  • tırnaksız genişleme üzerine destek yok
  • $IFSbayt yerine ilk karakteri
  • $*liste dışı bağlamda alıntı yapılmadığında $IFSboş olduğunda genişleme gibi bazı köşe durumu farklılıkları .

POSIX spesifikasyonları oldukça belirsiz olsa da, şimdi aşağı yukarı bash davranışını belirtiyor.

İçindeki kshveya bashiçindeki normal dizilerden farklıdır :

  • Endeksler (hariç 1 yerine 0 ° başlangıç "${@:0}"içeren $0bir konum parametresi (ve işlevlerde fonksiyonun adı ya da kabuk ve nasıl işlev tanımlandı) bağlı olmayan verir).
  • Öğeleri ayrı ayrı atayamazsınız
  • seyrek değil, öğeleri ayrı ayrı ayarlayamazsınız
  • shift kullanılabilir.

Olarak zshya da yashdiziler, normal diziler burada (değil seyrek endeksleri diğer kabukları ancak Ksh / deneme gibi bir başlar), $*normal bir dizi olarak işlenir. zshyer alır $argv(uyumluluk için bunun için bir takma csh). veya $*ile aynıdır (ilk karakterine katılan ancak yine de liste bağlamında ayrılmış bağımsız değişkenler ). Korn tarzı özel işlemlere benzer veya bunlardan geçer.$argv${argv[*]}$IFS"$@""${argv[@]}""${*[@]}"}


8

Ancak, veri yapısının ne olduğunu bilmiyorum $@.

Bu, konumsal parametrelerin değerlerine genişleyen özel bir parametredir ... Ama bu terminoloji hakkında nitel.

Konum parametrelerini bir parçası olarak görebiliriz $@, bu nedenle bağımsız olarak erişilebilen ve ardışık doğal sayılarla adlandırılan bir dizi farklı öğeye ( $1, $2...) sahiptir. Bu, genellikle dizi olarak adlandırılan bir şey yapar.

Sözdizimi biraz garip ve hatta sınırlı. Dizinin tek bir öğesini tek tek değiştirmenin bir yolu yoktur. Bunun yerine, her şey bir anda ayarlanmalıdır. ( set -- "$@" fooBir değer set -- "${@:1:2}" foo "${@:3}"eklemek veya ortasına değer eklemek için kullanabilirsiniz. Ancak her iki durumda da sonuç listesinin tamamını yazmanız gerekir.)

Neden $*çift ​​tırnak içine alındığında farklı davranır ,

Çünkü farklı davranıyorlar.

Bununla birlikte, echo $@bir dizi ise, sadece ilk eleman gösterilecek, tamamen basit ile yankılanabilir .

a=(foo bar asdf); echo $aSadece çıkacak olan gerçeği kastediyorsanız, foobu çoğunlukla kabuk sözdiziminin bir tuhaflığıdır ve ksh stili adlı dizilerin konumsal parametrelerden daha sonra oluşturulmuş olması ve $@. Düz $a, bir dizi veya basit bir skaler değişken ${a[0]}olup olmadığına bakılmaksızın, tek bir skaler değerin geriye dönük uyumlu anlamına sahiptir a.

@Tüm listeye ilişkin işaret, tüm listeyi "${a[@]}"almanın yolu olarak adlandırılmış dizilerle yeniden kullanıldı . Adlandırılmış dizilerle karşılaştırıldığında $@, gereksiz ayraçlar ve parantezler ve adlar atlanır.

Başka bir deyişle, $@bilgisayar belleğinde nasıl saklandığını bilmek istiyorum .

Bu, uygulamaya bağlıdır, önem verdiğiniz herhangi bir kabuğun kaynak koduna bakmanız gerekir.

Bu bir dize, çok satırlı bir dize mi yoksa bir dizi mi?

Çoğunlukla bir dizi. Diziler olarak adlandırılan ksh stilinden farklı olsalar da, sadece ardışık olanları değil, dizin olarak keyfi negatif olmayan tamsayılara sahip olabilirler $@. (Yani, adlandırılmış bir dizi seyrek olabilir ve örneğin dizinlere sahip olabilir 1, 3ve 4ile birlikte 0veya 2eksik olabilir. Konumsal parametrelerle bu mümkün değildir.)

Tek bir dize değildir, çünkü farklı öğelere genişletilebilir ve öğe satırlarını çağırmak da doğru değildir, çünkü herhangi bir normal değişken veya konum parametrelerinden biri (elemanları $@) da yeni satırlar içerebilir.

Benzersiz bir veri türüyse, bu değişkenin bir örneği olarak özel bir değişken tanımlamak mümkün müdür?

Hayır. Ancak adlandırılmış diziler muhtemelen daha yararlıdır.


1
+1. TL: DR $@bir veri yapısı değil , konum parametreleri veri yapısını genişleten birkaç işlevden / operatörden biridir .
Peter Cordes
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.