Gawk:将数组传递给函数


9

卡在GNU awk 3.1.6中,认为我已经解决了它的数组错误,但是在600行awk程序中仍然遇到了范围问题。需要验证对awk中数组作用域的理解才能找到我的错误。

给定这个说明性的awk代码...

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

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

print garray[1]

将打印...

global result

由于数组总是通过引用传递给函数,因此所有数组始终是全局的。无法创建本地数组。它是否正确?一直无法找到明确说明这一点的文档。

由于我正在调试,并且3.1.6本身在该区域中存在已知的错误,因此我试图确定awk的错误在哪里消失并从我的那里开始。

补充:那么ga []为什么在函数内部起作用?

首先,foo(ga)实际上不需要将数组传递给函数。只需以garray[]在函数内部进行。这样做并没有可衡量的性能损失,它有助于调试和错误报告。

在使用中foo(ga)ga[]是全局数组的同义词garray[]。与其成为的本地副本garray[],不如说是一个指向garray[],而是,就像符号链接是指向文件的指针一样,因此可以使用多个名称访问同一文件(或数组)。

补充:澄清格伦·杰克曼的答案

虽然在函数外部创建的数组对于函数是全局的,可以传递给函数,也可以在函数内部引用,但是函数内部创建的数组的确确实在函数本地,并且在函数外部不可见。修改杰克曼先生的例子说明了这一点...

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[]数组(实际上只是指向它的指针)传递给bar()。该y[]阵列甚至不存在,直到我们得到里面的功能。

但是,如果我们声明y[]通过将其包括在bar()参数列表中而未在函数外部分配任何内容来声明,则在调用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

最后,如果我们y[]在函数外部创建数组并将其传递给bar(x,y)split()则函数内部的赋值将替换该数组的元素...

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

Answers:


5

功能参数是该功能的本地参数。

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: 

如果传递给函数的值少于参数,则多余的参数将为空。您有时可能会看到定义的函数,例如

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

其中空格后的参数是局部变量,并且不打算在调用时取值。

没有理由为什么这不适用于本地数组:

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文件清楚地表明,数组通过引用传递,而且也没有记载围绕这种方式。行为与gawk4.0.1 相同。

POSIX指定该行为,所以我不希望您会发现任何awk其他行为。

如果需要该功能,可以使用perlperl带有工具(a2p)将awk脚本转换为perl

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.