Gawk: Dizileri işlevlere geçirme


9

GNU awk 3.1.6 ile sıkışmış ve dizi hataları etrafında çalıştım ama hala bir 600-çizgi awk programında bir kapsam sorunu gibi görünüyor düşünüyorum. Benim hata bulmak için awk dizi kapsamı anlamak doğrulamak gerekiyor.

Bu açıklayıcı awk kodu göz önüne alındığında ...

function foo(ga) {
  ga[1] = "global result"
}

garray[1] = "global"
foo(garray)

print garray[1]

yazdırılacak ...

global result

Diziler her zaman referans olarak işlevlere geçirildiğinden, tüm diziler her zaman globaldir. Yerel dizi oluşturmanın bir yolu yoktur. Bu doğru mu? Açıkça söyleyen dokümanları bulamadım.

Hata ayıkladığım ve 3.1.6'nın kendisi bu alanda hataları bildiğinden, awk hatalarının nerede bırakıldığını ve benimkinin başladığını belirlemeye çalışıyorum.

Tamamlayıcı: ga [] neden işlevin içinde çalışır?

Her şeyden önce, diziyi işleve geçirmek foo(ga)aslında gereksizdir. Sadece garray[]işlevin içindeki gibi erişin . Ancak bunu yaparken ölçülebilir bir performans cezası yoktur ve hata ayıklama ve hata raporlamaya yardımcı olur.

Kullanırken foo(ga), ga[]küresel diziye eşanlamlıdır garray[]. Bunun yerel bir kopyası olmak yerine garray[], yalnızca bir işaretçi garray[], sembolik bir bağlantı bir dosyanın işaretçisi gibi ve aynı dosyaya (veya diziye) birden fazla ad altında erişilebilir.

Ek: Glenn Jackman'ın cevabının açıklığa kavuşturulması

Bir fonksiyonun dışında yaratılan diziler fonksiyon için geneldir ve ona aktarılabilir veya sadece referansta bulunabilirken, bir fonksiyonun içinde yaratılan diziler gerçekten fonksiyon için yerel kalır ve onun dışında görünmez. Bay Jackman'ın örneğini değiştirmek bunu göstermektedir ...

awk '
    function bar(x,y) {
      split("hello world", y)
      print "x[1] inside: " x[1]
      print "y[1] inside: " y[1]
    }
    BEGIN {
      x[1]="goodbye"
      print "x[1] before: " x[1]
      print "y[1] before: " y[1]
      bar(x)
      print "x[1] after: " x[1]
      print "y[1] after: " y[1]
    }
'
x[1] before: goodbye
y[1] before: 
x[1] inside: goodbye
y[1] inside: hello
x[1] after: goodbye
y[1] after: 

x[]Diziyi yalnızca (aslında, yalnızca bir işaretçi) konumuna geçirdiğimizi unutmayın bar(). y[]Biz işlevi içinde elde edene kadar dizi bile yok.

Diye ilan Ancak, y[]bunu dahil ederek bar()fonksiyonu dışında buna bir şey atamadan argüman listesinin, bu çağrı sonrasında görünür hale gelir bar(x,y)...

awk '
    function bar(x,y) {
      split("hello world", y)
      print "x[1] inside: " x[1]
      print "y[1] inside: " y[1]
    }
    BEGIN {
      x[1]="goodbye"
      print "x[1] before: " x[1]
      print "y[1] before: " y[1]
      bar(x,y)
      print "x[1] after: " x[1]
      print "y[1] after: " y[1]
    }
'
x[1] before: goodbye
y[1] before: 
x[1] inside: goodbye
y[1] inside: hello
x[1] after: goodbye
y[1] after: hello

Son olarak, biz oluşturursanız y[]fonksiyonu dışında diziyi ve ile pass bar(x,y), split()fonksiyon yerine geçer o Dizinin elamanları içeride atama ...

awk '
    function bar(x,y) {
      split("hello world", y)
      print "x[1] inside: " x[1]
      print "y[1] inside: " y[1]
    }
    BEGIN {
      x[1]="goodbye"
      y[1]="howdy"
      print "x[1] before: " x[1]
      print "y[1] before: " y[1]
      bar(x,y)
      print "x[1] after: " x[1]
      print "y[1] after: " y[1]
    }
'
x[1] before: goodbye
y[1] before: howdy
x[1] inside: goodbye
y[1] inside: hello
x[1] after: goodbye
y[1] after: hello

Yanıtlar:


6

Fonksiyon parametreleri fonksiyon için yereldir.

awk '
    function foo(x,y) {y=x*x; print "y in function: "y} 
    BEGIN {foo(2); print "y out of function: " y}
'
y in function: 4
y out of function: 

Bir işleve parametrelerden daha az değer iletirseniz, fazladan parametreler boştur. Bazen şu şekilde tanımlanmış işlevler görebilirsiniz:

function foo(a, b, c            d, e, f) {...

burada boşluktan sonraki parametreler yerel değişkenlerdir ve çağırmada bir değer alması amaçlanmamıştır.

Bunun yerel diziler için çalışamamasının bir nedeni yok:

awk '
    function bar(x) {
        split("hello world", x)
        print "in: " x[1]
    }
    BEGIN {
        x[1]="world"
        bar()
        print "out: " x[1]}
'
in: hello
out: world

3

Gawk dokümantasyon o diziler referans olarak yansıtılması anlamına temizlemek yapar ve hiçbir etrafında yolu var belgeli. Davranış gawk4.0.1 ile aynıdır .

POSIX bu davranışı belirtir , bu yüzden awkbaşka şekilde davranan herhangi bir uygulama bulacağınızı beklemiyorum .

Bu işlevselliğe ihtiyacınız varsa kullanabilirsiniz perl. komut dosyalarını çevirmek için perlbir araç ( a2p) ile birlikte gelir .awkperl

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.