我尝试运行这样的单行命令
touch ./py.py; awk 'BEGIN{print FILENAME}' ./py.py
并期望得到结果./py.py
,但只得到一个空行。但是,如果我没有BEGIN
阻止,它会起作用:
touch ./py.py; awk '{print FILENAME}' ./py.py
似乎该变量在块FILENAME
中不可用。BEGIN
这是为什么?如何在BEGIN
块中使用该变量?
awk 可以在一次调用中处理多个文件(例如awk '{whatever}' file1 file2 file3
)。BEGIN 块在 awk 启动时执行,在它打开第一个文件之前,而不是在每个文件的开头(END 块类似)。有人可能会争辩说,将 awk 扩展为具有每个文件的 BEGIN/END 挂钩可能很有用,但它们在我使用的任何当前版本的 awk/nawk/gawk 中都不存在......
事后总结:
在gawk (GNU awk) 4
或更高版本中,使用BEGINFILE
而不是BEGIN
确保FILENAME
已定义;但是请注意,BEGINFILE
顾名思义,每个输入文件都会调用 .
在其他awk
变体中,仅BEGIN
提供,此时FILENAME
尚未定义,因为根据设计,输入文件处理尚未开始。(相比之下,块FILENAME
中确实有一个值END
,即最后处理的文件。)
解决方法:
您可以通过内置参数访问传递给 awk的文件名ARGV
参数,其中ARGV[1]
报告第一个文件名参数、ARGV[2]
第二个文件名参数,依此类推。
stdin
输入ARGV[1]
将是一个空字符串。VAR=10
)。因此,假设没有伪文件名,ARGV[1]
在处理[第一个]文件时,BEGIN
块中的内容相当于FILENAME
后面的块。
Caveat re implicit use of stdin
: BSD awk
(e.g., on OSX) reports implicit stdin
input also as an empty string in FILENAME
(in later blocks), whereas mawk
and gawk
report "-"
.
All 3 variants, however, support explicit stdin
input by passing -
as a filename argument, in which case FILENAME
returns "-"
in all 3 variants.
确实 FILENAME 在 awk 的 BEGIN 块中不可用。事实上,awk 不会在 BEGIN 块中开始处理输入文件,因此没有设置这个内部变量。甚至这个命令:
awk 'BEGIN{print;}' ./file
不会打印文件中的任何内容。
虽然我不知道这有什么更深层次的意义,但我仍然可以想出一个技巧。不过,我不会称其为“解决方案”。不过,这是打发时间的好方法。;)
这是最初的工作单线之一:
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 块中(因此将文件作为参数忽略),我们将不得不通过使用-builtin数组的偷偷摸摸的方法来模拟这种行为,就好像awk
行后面的参数是一个文件一样,例如:awk
ARGV[]
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