Gawk:将数组传递给函数

Gawk:将数组传递给函数

坚持使用 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[]在函数内部访问它即可。然而,这样做不会造成明显的性能损失,并且有助于调试和错误报告。

在 using 中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

答案1

函数参数是函数的局部参数。

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

答案2

gawk 文档清楚地表明数组是通过引用传递的,并且没有记录的方法可以解决这个问题。该行为与 4.0.1 相同gawk

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

如果您需要该功能,您可以使用perl.perl附带一个工具 ( a2p) 将awk脚本翻译为perl.

相关内容