Gawk: passare array a funzioni


9

Bloccato con GNU awk 3.1.6 e penso di aver aggirato i suoi bug di array ma ho ancora quello che sembra un problema di ambito in un programma awk a 600 righe. È necessario verificare la comprensione dell'ambito dell'array in awk per trovare il mio bug.

Dato questo codice illustrativo awk ...

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

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

print garray[1]

stamperà ...

global result

Poiché le matrici vengono sempre passate alle funzioni per riferimento, tutte le matrici sono sempre globali. Non è possibile creare un array locale. È corretto? Non sono riuscito a trovare documenti che lo affermino esplicitamente.

Dal momento che sto eseguendo il debug, e 3.1.6 stesso ha riscontrato bug in quest'area, sto cercando di determinare dove si interrompono i bug di Awk e iniziano i miei.

Supplemento: perché ga [] funziona all'interno della funzione allora?

Prima di tutto, passare l'array alla funzione con non foo(ga)è effettivamente necessario. Basta accedervi come garray[]all'interno della funzione. Non vi è alcuna penalità misurabile nelle prestazioni nel farlo, tuttavia, aiuta nel debug e nella segnalazione degli errori.

Nel usando foo(ga), ga[]è un sinonimo per l'array globale garray[]. Invece di essere una copia locale di garray[], è semplicemente un puntatore a garray[], piuttosto come un collegamento simbolico è un puntatore a un file e quindi è possibile accedere allo stesso file (o array) con più di un nome.

Supplemento: chiarimento della risposta di Glenn Jackman

Mentre le matrici create al di fuori di una funzione sono globali alla funzione e possono essere passate ad essa o semplicemente citate al suo interno, le matrici create all'interno di una funzione rimangono effettivamente locali alla funzione e non visibili al di fuori di essa. La modifica dell'esempio di Mr. Jackman illustra questo ...

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: 

Si noti che stiamo solo passando l' x[]array (in realtà, solo un puntatore ad esso) a bar(). L' y[]array non esiste nemmeno finché non entriamo nella funzione.

Tuttavia, se dichiariamo y[]includendolo nell'elenco degli bar()argomenti senza assegnare nulla al di fuori della funzione, diventa visibile dopo aver chiamato 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

Infine, se creiamo l' y[]array all'esterno della funzione e lo passiamo con bar(x,y), l' split()assegnazione all'interno della funzione sostituisce gli elementi dell'array ...

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

Risposte:


5

I parametri della funzione sono locali per la funzione.

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: 

Se si passano meno valori a una funzione di quanti siano i parametri, i parametri aggiuntivi sono semplicemente vuoti. A volte potresti vedere funzioni definite come

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

dove i parametri dopo lo spazio bianco sono variabili locali e non intendono assumere un valore durante l'invocazione.

Nessun motivo per cui questo non può funzionare per gli array locali:

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

La documentazione gawk chiarisce che le matrici vengono passate per riferimento e non esiste alcun modo documentato per aggirare ciò. Il comportamento è lo stesso con gawk4.0.1.

POSIX specifica quel comportamento , quindi non mi aspetto che troverai awkimplementazioni che si comportino diversamente.

Se hai bisogno di quella funzionalità, puoi usare perl. perlviene fornito con uno strumento ( a2p) in cui tradurre gli awkscript perl.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.