Bash işaretçilerin kullanımı için destek sağlıyor mu?


12

Basit soru. Bash kabuğunun bir kabuk betiği yazarken işaretçiler kullanma desteği var mı?

Ben ${var[@]}dizi üzerinde yineleme yaparken , genişleme gösterim aşina $var, ama bu dizi dizinleri üzerinde yineleme için işaretçiler kullanarak açık değildir. Bash diğer diller gibi bellek adreslerine erişim sağlıyor mu?

Eğer bash işaretçilerin kullanılmasını desteklemiyorsa, diğer mermiler ne yapar?

Yanıtlar:


28

Bir işaretçi ( belleğin bir yerine ), Python veya kabuk gibi bir şey olsun, C'den daha yüksek bir şeyde gerçekten yararlı bir kavram değildir. Nesnelere yapılan göndermeler elbette üst düzey dillerde yararlıdır, belki de karmaşık veri yapıları oluşturmak için bile gereklidir. Ancak çoğu durumda bellek adresleri açısından düşünmek çok yararlı olamayacak kadar düşük düzeydedir.

Bash'te (ve diğer kabuklarda), dizi öğelerinin değerlerini ${array[index]}gösterimle array[index]=...alabilir, bunları atayabilir ve dizideki öğelerin sayısını alabilirsiniz ${#array[@]}. Parantez içindeki ifade aritmetik bir ifadedir. Bir örnek olarak, tüm dizi üyelerine sabit bir önek ekleyebiliriz:

for ((i=0 ; i < ${#array[@]} ; i++ )) ; do
    array[i]="foo-${array[i]}"
done

(İndeksleri değil, sadece değerleri önemseseydik for x in "${array[@]}" ; do...iyi olur.)

İle ilişkisel veya seyrek diziler , sayısal döngü çok mantıklı değil, ama onun yerine biz dizi tuşları / dizinleri getirmesi gerekiyordu ${!array[@]}. Örneğin

declare -A assoc=([foo]="123" [bar]="456")
for i in "${!assoc[@]}" ; do 
    echo "${assoc[$i]}"
done 

Buna ek olarak, Bash'in dolaylı olarak başka bir değişkeni göstermenin iki yolu vardır:

  • Dolaylı genişletme kullanılarak sözdizimini değişkeninin değerini kullanır, adı olan , ve${!var}var
  • declareyerleşik (veya -uyumluksh eşanlamlı typeset) ile oluşturulması gereken aderefs . declare -n ref=varyapar refdeğişken bir referans var.

Namerefs da destek indeksleme, biz varsa ki arr=(a b c); declare -n ref=arr;o ${ref[1]}kadar genişleyecektir b. Kullanılması ${!p[1]}yerine alacaktı pbir dizi olarak ve ikinci elemanı tarafından adındaki değişkene bakın.

Bash, namerefs tarafından o, referanslar anlamıyla isim ve bir işlev içinden bir nameref kullanılarak isimli değişkenin yerel değerini kullanır. Bu yazdırılacaktır local value of var.

#!/bin/bash
fun() {
        local var="local value of var"
        echo "$ref";
}
var="global var"
declare -n ref=var
fun

BashFAQ'nun dolaylı yayın konusunda da daha uzun bir makalesi var .


2
dolaylı anlatım üst düzey dillerde oldukça yararlıdır. örneğin perl. C işaretçileriyle aynı değiller, ancak aynı temel işleve hizmet ediyorlar. Bash bile değişkenlere dolaylı olarak erişebilir ... ancak IMO özelliği önemli ölçüde kullanan bir kod yazmaya başlarsanız, perl ya da başka bir şeyle sıfırdan başlamak daha iyidir. Ayrıca bkz. Mywiki.wooledge.org/BashFAQ/006
cas

2
@cas, oh, kesinlikle. Ancak bunları bellek adreslerinden ziyade nesnelere işaret olarak düşünmek daha iyidir. (C'de bile dahil olan bir tür var.) Hem dolaylı genişlemeyi hem de namerefleri not etmek istedim, ancak bunu hemen yapacak zamanım yoktu.
ilkkachu

Büyük olasılıkla, for-loop örneğinin, for foo in "${array[@]}" ; do ... donebaşka amaç (lar) için dizine ihtiyacınız olmadığı sürece daha doğal olarak yazıldığını belirtmek gerekir.
Crawford

@WillCrawford, gelin. örneği düzenledi ve not etti.
ilkkachu

9

Hayır, bash"işaretçiler" yok, ancak referansları var:

$ spam="fred"
$ declare -n tripe=spam
$ echo $tripe
fred
$ tripe=juki
$ echo $spam
juki

Gönderen bashadam sayfası:

Bir değişken, bir aderef oluşturmak için declareya da localyerleşik komutlarına -n seçeneği kullanılarak nameref özniteliğini veya başka bir değişkene bir başvuru atayabilir. Bu, değişkenlerin dolaylı olarak değiştirilmesine izin verir. Nameref değişkenine her başvuruda bulunulduğunda, atandığında, ayarlanmadığında veya özniteliklerinde değişiklik yapıldığında (nameref özniteliğinin kendisini kullanmak veya değiştirmek dışında), işlem aslında nameref değişkeninin değeri tarafından belirtilen değişken üzerinde gerçekleştirilir. Bir nameref, kabuk işlevleri içinde, adı işleve argüman olarak iletilen bir değişkeni ifade etmek için yaygın olarak kullanılır. Örneğin, bir değişken adı kabuk işlevine ilk bağımsız değişkeni olarak iletilirse,

declare -n ref=$1

işlevin içinde, değeri ilk bağımsız değişken olarak iletilen değişken adı olan bir nameref değişkeni oluşturur. Ref'ye yapılan atıflar ve atamalar ile özniteliklerinde yapılan değişiklikler, adı $ 1 olarak iletilen değişkene yapılan başvurular, atamalar ve öznitelik değişiklikleri olarak kabul edilir. For döngüsünde kontrol değişkeni nameref özniteliğine sahipse, sözcük listesi kabuk değişkenlerinin bir listesi olabilir ve döngü yürütüldüğünde listedeki her sözcük için bir ad başvurusu oluşturulur. Dizi değişkenlerine nameref niteliği verilemez. Ancak, nameref değişkenleri dizi değişkenlerine ve abone dizi değişkenlerine başvurabilir. Namerefs unsetyerleşik -n seçeneği kullanılarak ayarlanamaz . Aksi takdirde,unset bağımsız değişken olarak bir nameref değişkeninin adıyla yürütülürse, nameref değişkeni tarafından başvurulan değişken ayarlanamaz.


4

Hayır, mermilerde "işaretçiler" kullanılmaz (C'de anlaşıldığı gibi).

Diziler dizinleri kullanabilir: echo "${array[2]}"ancak @örneğinizdeki gerçekten bir "işaretçi" değildir. "Dizi değerleri listesini" ifade etmenin bir yoludur. Kabuk ayrıştırıcısının anladığı bir şey. A yöntemine benzer:

$ echo "$@"

tüm "Konumsal Parametreler" listesine genişler.


2

Bash tamsayı dizine alınmış diziler tanımlanabilir ve yinelemeli olarak erişilebilir;

declare -a obj
obj+=("val1")
obj+=("val2")

for item in ${obj[@]}; do
  echo "${obj[${item}]} ${item}"
done

Bash'deki ilişkisel veya dize tabanlı dizinlenmiş diziler aşağıdaki yinelemeli tanımlamayı gerektirir;

declare -A obj
obj["key1"]="val1"
obj["key2"]="val2"

for item in ${!obj[@]}; do
  echo "${obj[${item}]} ${item}"
done

Göstericilerle ilgili soruyu bash'tan kullanmak; derlenmiş bash binary'nin dahili işlevselliği gerçekten de yığına tahsis edilen belleğe işaretçiler kullanır ve kullanımı ile benzer işlevleri ortaya çıkarır eval. Bkz. [Dolaylı referanslar] http://tldp.org/LDP/abs/html/ivr.html )

Ejderhalar var; kullanımı evalgüvenlik sonuçları nedeniyle dikkatli kullanılmalıdır

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.