Preso com o GNU awk 3.1.6 e acho que trabalhei em torno de seus bugs de array, mas ainda tenho o que parece ser um problema de escopo em um programa awk de 600 linhas. Preciso verificar a compreensão do escopo da matriz no awk para encontrar meu bug.
Dado este código awk ilustrativo ...
function foo(ga) {
ga[1] = "global result"
}
garray[1] = "global"
foo(garray)
print garray[1]
imprimirá ...
global result
Como as matrizes são sempre passadas para as funções por referência, todas as matrizes são sempre globais. Não há como criar um array local. Isso está correto? Não foi possível encontrar documentos que explicitamente digam isso.
Como estou depurando, e o 3.1.6 em si já conhece bugs nesta área, estou tentando determinar onde os bugs do awk terminam e os meus começam.
Suplemento: por que o ga [] funciona dentro da função?
Primeiro, passar a matriz para a função com foo(ga)
é realmente desnecessário. Basta acessá-lo como garray[]
dentro da função. Não há penalidade de desempenho mensurável ao fazê-lo, e isso ajuda na depuração e no relatório de erros.
Ao usar foo(ga)
, ga[]
é um sinônimo para a matriz global garray[]
. Em vez de ser uma cópia local de garray[]
, é simplesmente um ponteiro para garray[]
, da mesma forma que um link simbólico é um ponteiro para um arquivo e, portanto, o mesmo arquivo (ou matriz) pode ser acessado sob mais de um nome.
Suplemento: esclarecimento da resposta de Glenn Jackman
Enquanto os arrays criados fora uma função são globais para a função e podem ser passados para ela ou apenas referenciados dentro dela, arrays criados dentro de uma função permanecem locais para a função e não visível fora dela. Modificando o exemplo do Sr. Jackman ilustra isso ...
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:
Observe que estamos passando apenas o array x[]
(na verdade, apenas um ponteiro para ele) para bar()
. A matriz y[]
não existe até chegarmos à função.
No entanto, se declararmos y[]
incluindo-o na lista de argumentos bar()
sem atribuir nada a ele fora da função, ele ficará visível depois de chamar 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
Finalmente, se criarmos a matriz y[]
fora da função e passá-la com bar(x,y)
, a atribuição split()
dentro da função substituirá os elementos dessa matriz ...
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