如何在awk中的BEGIN块中使用变量?

时间:2012-06-06 14:20:39

标签: shell awk

我尝试像这样运行一行命令

touch ./py.py; awk 'BEGIN{print FILENAME}' ./py.py 

并期望得到结果./py.py,但只得到一个空行。但是,如果我在没有BEGIN块的情况下执行此操作,则可以:

touch ./py.py; awk '{print FILENAME}' ./py.py

似乎FILENAME块中没有BEGIN变量。这是为什么?如何在BEGIN块中使用该变量?

4 个答案:

答案 0 :(得分:4)

Awk可以在一次调用中处理多个文件(例如awk '{whatever}' file1 file2 file3)。当awk启动时,在打开第一个文件之前执行BEGIN块,而不是在每个文件的开头执行(END块类似)。有人可能会说,将awk扩展为具有每个文件的BEGIN / END挂钩可能会有用,但是在我使用的任何当前版本的awk / nawk / gawk中都不存在...

答案 1 :(得分:1)

确实,在awk的BEGIN块中没有FILENAME。事实上,awk没有开始处理BEGIN块中的输入文件,因此未设置此内部变量。甚至这个命令:

awk 'BEGIN{print;}' ./file

不会从文件中打印任何内容。

答案 2 :(得分:1)

总结后见之明的好处:

  • gawk (GNU awk) 4或更高版本中,使用BEGINFILE代替BEGIN可确保定义FILENAME;但请注意,BEGINFILE,顾名思义,是为每个输入文件调用的。

  • 在仅提供awk的其他BEGIN变体中, FILENAME尚未定义,因为,按设计, 输入文件处理尚未开始。 (相比之下,FILENAME END块中有一个值,即已处理的 last 文件。)

解决方法

您可以通过内置参数ARGV访问传递给awk的文件名参数,其中ARGV[1]报告第一个文件名参数ARGV[2]第二,等等。

  • 请注意,选项和隐含的stdin输入计数,因此使用隐式stdin输入ARGV[1]将是空字符串
  • 相比之下,充当变量赋值的伪文件名计数(例如,VAR=10)。

因此,假设没有伪文件名,ARGV[1]块中的BEGIN在后​​续块中等同于FILENAME,而正在处理[first]文件。

警告隐含使用stdin BSD awk(例如,在OSX上)报告隐式stdin输入也作为{{1}中的空字符串(在后面的块中),而FILENAMEmawk报告gawk。 但是,所有3个变体都通过将"-"作为文件名参数传递来支持显式 stdin输入,在这种情况下,-会在所有3中返回FILENAME变体。

答案 3 :(得分:0)

虽然我不知道对此有何深层意义,但我仍然可以想出一个黑客。我不会称之为“解决方案”。不过,这是一个很好的方式来消磨时间。 ;)

这是最初的工作单线之一:

touch ./py.py; awk '{print FILENAME}' ./py.py 

为此,您必须知道awk 物理检查媒体上是否存在该文件。因此,如果我们尝试过这样的事情:

awk '{print FILENAME}' ./py2.py 

awk将获得拯救:

awk: cmd. line:1: fatal: cannot open file `./py2.py' for reading (No such file or directory)

好的。所以如果我们在一个BEGIN块中(因此将文件作为参数被忽略),我们必须模拟这种行为,好像awk背后的参数一样line 一个文件,通过偷偷摸摸的方法使用awk - 内置ARGV[]数组,e。 G。像这样:

awk 'BEGIN {$0 = ARGV[1]; if ((getline <$0) == -1) print "ERROR: File not found: " $0; else print ARGV[1]}' ./py.py

这将给出结果:

./py.py

到目前为止,这么好。现在为什么不刻意使用我们在物理媒体上没有的文件:

awk 'BEGIN {$0 = ARGV[1]; if ((getline <$0) == -1) print "ERROR: File not found: " $0; else print ARGV[1]}' ./py2.py

将导致

ERROR: File not found: ./py2.py

因此,我们实际检查文件是否存在(如awk在非FILENAME块中与BEGIN一样)并在文件不存在时吐出错误。 相当无意义的IMO,但是 - 唉,如果我们总是不得不质疑一个解决方案实际上是多么明智,我们需要一生一世的时间,特别是在政治方面。 :)