我有这个最小的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