GNU awk 希望将参数视为路径

GNU awk 希望将参数视为路径

我有这个最小的awk例子:

#!/usr/bin/awk -f
BEGIN {
  if (ARGC>1)
    a=ARGV[1]
  else
    a=5
}

{
  print
}

ls -l|./t.awk, 调用它会产生:

$ ls -l|./t.awk 2
awk: ./t.awk:4: fatal: cannot open file `2' for reading (No such file or directory)

当不带参数()调用它时ls -l|./t.awk,没有问题。

因此,我的第一个问题是,它不是简单的字符串相等性检查,而是尝试读取名为“2”的文件。

第二个令人惊讶的事情是,删除第二个块使其能够正常工作! (给出空输出。)

#!/usr/bin/awk -f
BEGIN {
  if (ARGC>1)
    a=ARGV[1]
  else
    a=5
}

原因是什么?

答案1

尽管 awk 向您提供了参数,但您可以将它们操纵为您最终想要的东西。例如,只需将 arg 设置为空:

if (ARGC>1) {a=ARGV[1]; ARGV[1]=""}
else a=5

否则,args 具有其正常功能,对于非选项来说是输入文件名。因此 awk 将尝试读取文件“2”并在其上运行脚本主体。

答案2

当您在命令行上将参数传递给 awk 时,它假定您正在给它一个文件,因此它会尝试打开它。我真的不明白你期望发生什么,这就是 awk 通常的行为方式。

如果删除它,它会起作用的原因{ print }也很简单。如果删除它,则只剩下一个BEGIN{}块,该块在读取任何输入文件之前运行。由于除了 之外没有任何内容BEGIN{},因此没有理由尝试读取文件,并且程序退出。这可以通过以下方式轻松确认strace

$ strace awk 'BEGIN{a=1}{print}' somefile |& grep 'open.*somefile'
openat(AT_FDCWD, "somefile", O_RDONLY)  = -1 ENOENT (No such file or directory)
write(2, "cannot open file `somefile' for "..., 66cannot open file `somefile' for reading: No such file or directory) = 66

将以上内容与以下内容进行比较:

$ strace awk 'BEGIN{a=1}' somefile |& grep 'open.*somefile'
$ 

由于无需对该文件执行任何操作,因此不会尝试打开它。


我认为您正在寻找的是foo=bar允许您在命令行传递变量的格式:

ls -l|./t.awk a=2

接下来,将脚本更改为:

#!/bin/awk -f
BEGIN {
  if (!a){
    a=5
  }
}

{
  print a,$0
}

并说明其工作原理:

$ echo foo | t.awk          ## default value
5 foo
$ echo foo | foo.awk a=12   ## value given at launch
12 foo

或者,当直接从命令行运行时,您也可以使用该-v选项来执行相同的操作:

$ awk -v a=12 'BEGIN{print a}'
12

相关内容