@include在 awk 中,为什么不执行这个库函数?

@include in awk, why isn't this library function executed?

提问人:John Smith 提问时间:11/16/2023 最后编辑:John Smith 更新时间:11/16/2023 访问量:53

问:

我试图通过执行 - 包含以下内容的脚本来使用当前工作目录中的函数库:lib-of-fns.awkusing-fns.awk

#!/usr/bin/awk -f

@include "lib-of-fns.awk"
BEGIN { print_all("using-fns.awk") }

内容是:lib-of-fns.awk

#!/usr/bin/awk -f

function print_all(fname) {
  /.*/ fname
}


它不起作用 - 在我的标准输出中没有输入任何文件,而如果我手动运行命令,我会将内容打印到屏幕上。为什么会这样?awk '/.*/' using-fns.awkusing-fns.awk

P.S. 使用 gawk。

awk 函数

评论


答:

3赞 Ed Morton 11/16/2023 #1

这与库无关,您的函数不会在单个文件或脚本中工作,即:print_all

awk '
    function print_all(fname) {
      /.*/ fname
    }
    BEGIN { print_all("using-fns.awk") }
'

不会产生任何输出,因为它与您似乎尝试执行的语法不接近。

在增加将它们放入单独的库文件中的复杂性之前,您应该测试从同一文件/脚本中调用任何库函数时是否正常工作。你的函数等同于编写:

    function print_all(fname,      rslt) {
      if ($0 ~ /.*/) {
        rslt = 1
      }
      else {
        rslt = 0
      }
      rslt fname   # concatenates 2 strings and does nothing with the result.
    }

如果您尝试从作为参数传递的文件名中打印与正则表达式匹配的每一行(将是所有行),请更改以下内容:.*

function print_all(fname) {
  /.*/ fname
}

对此:

function print_all(fname,    line) {
    while ( (getline line < fname) > 0 ) {
        if ( line ~ /.*/ ) {
            print line
        }
    }
    close(fname)    # just to be sure
}

然后,您可以使用以下命令对其进行测试:

$ seq 3 > "using-fns.awk"
$ awk '
awk '
function print_all(fname,    line) {
    while ( (getline line < fname) > 0 ) {
        if ( line ~ /.*/ ) {
            print line
        }
    }
    close(fname)    # just to be sure
}
BEGIN { print_all("using-fns.awk") }
'
1
2
3

我假设测试只是一个用于测试目的的示例,您真的不会不必要地将每一行与 进行比较。/.*/.*

不过,请务必在使用前阅读并完全理解 http://awk.freeshell.org/AllAboutGetlinegetline

或者,如果你想保持与当前语法相似的语法,你可以生成一个子 shell 来从你的函数调用 awk:

$ awk '
function print_all(fname) {
    system("awk \047/.*/\047 \047" fname "\047")
}
BEGIN { print_all("using-fns.awk") }
'
1
2
3

但这将是毫无意义和低效的,并且在将主脚本的输出与从子 shell 调用的脚本的输出混合时可能会产生意外的输出排序,所以我不会这样做。

FWIW 如果我要编写一个脚本来打印与脚本中确定名称的文件中的某个正则表达式匹配的行,我通常会执行以下操作,而不是在循环中调用或生成子 shell:getline

$ awk 'BEGIN{ARGV[ARGC++]="using-fns.awk"} /.*/'
1
2
3

顺便说一句 - 不要用 shebang 来称呼 awk