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

bsint 发布于 2019-01-15 awk 最后更新 2019-01-15 22:14 227 浏览

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

touch ./py.py; awk 'BEGIN{print FILENAME}' ./py.py 
并期望得到./py.py的结果,但只能得到空行。但是,如果我在没有BEGIN块的情况下执行此操作,它将起作用:
touch ./py.py; awk '{print FILENAME}' ./py.py
看起来FILENAME变量在BEGIN块中不可用。这是为什么?我如何在BEGIN块中使用该变量?

znon 2019-01-15

赞同来自:

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

awk 'BEGIN{print;}' ./file
不会从文件中打印任何内容。

bsit 2019-01-15

赞同来自:

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

kaut 2019-01-15

赞同来自:

总结后见之明的好处:

  • gawk (GNU awk) 4或更高版本中,使用BEGINFILE代替BEGIN可确保定义FILENAME;但请注意,BEGINFILE,顾名思义,是为每个输入文件调用的。
  • 在仅提供BEGIN的其他awk变体中,此时尚未定义FILENAME,因为根据设计,输入文件处理尚未开始。 (相比之下,FILENAME确实在END块中有一个值,即处理的最后一个文件。)
解决方法: 您可以通过内置参数ARGV访问传递给awk的文件名参数,其中ARGV[1]报告第一个文件名参数,ARGV[2]报告第二个,依此类推。
  • 请注意,选项和隐含的stdin输入不计算,因此使用隐式stdin输入时,ARGV[1]将为空字符串。
  • 相比之下,充当变量赋值的伪文件名确实有效(例如,VAR=10)。
因此,假设没有伪文件名,BEGIN块中的ARGV[1]相当于后续块中的FILENAME,而正在处理[first]文件。 买者再隐式使用stdin的:BSD awk(例如,在OSX)也报道隐stdin输入作为在FILENAME一个空字符串(在以后的块),而mawkgawk报告"-"。 但是,所有3个变体都通过将-作为文件名参数传递来支持显式stdin输入,在这种情况下,FILENAME在所有3种变体中返回"-"

qui_id 2019-01-15

赞同来自:

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

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行背后的参数是一个文件,通过偷偷摸摸的方法使用awk-builtin ARGV[]array,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
因此,我们实际检查文件是否存在(如awkFILENAME在非BEGIN块中一样),如果文件不存在则吐出错误。 相当无意义的IMO,但是 - 唉,如果我们总是不得不质疑解决方案究竟是多么明智,那么我们需要一生的跨度,特别是在政治方面。 :)