我有一个awk
脚本,我正在对一对文件运行。我这样称呼它:
awk -f script.awk file1 file2
script.awk看起来像这样:
BEGIN {FS=":"}
{ if( NR == 1 )
{
var=$2
FS=" "
}
else print var,"|",$0
}
每个文件的第一行是冒号分隔的。对于每一行,我希望它返回默认的空白文件分隔符。
这适用于第一个文件,但是因为FS
在每个文件后没有重置为:
而失败,因为BEGIN块只处理了一次。
tldr:有没有办法让awk处理BEGIN块一次为我传递的每个文件?
我在cygwin bash上运行它,以防万一。
答案 0 :(得分:8)
如果您使用的是gawk
版本4或更高版本,则会出现BEGINFILE
块。从手册:
BEGINFILE和ENDFILE是其他特殊模式,它们的主体在读取第一个之前执行 记录每个命令行输入文件并在读取每个文件的最后一条记录之后。在BEGINFILE里面 规则,如果文件可以成功打开,ERRNO的值将为空字符串。否则,那里 是文件的一些问题,代码应该使用nextfile跳过它。如果不这样做,gawk会产生 对于无法打开的文件,它通常会出现致命错误。
例如:
touch a b c
awk 'BEGINFILE { print "Processing: " FILENAME }' a b c
输出:
Processing: a
Processing: b
Processing: c
如 DennisWilliamson 所述,您可以在脚本开头使用FNR == 1
获得类似的效果。除此之外,您可以直接从命令行更改FS
,例如:
awk -f script.awk FS=':' file1 FS=' ' file2
此处FS
变量将保留以前的任何值。
答案 1 :(得分:4)
而不是:
BEGIN {FS=":"}
使用:
FNR == 1 {FS=":"}
答案 2 :(得分:3)
FNR
变量可以为您提供帮助。它与NR
相同,除了它在文件范围内,因此每个输入文件都会重置为1。
http://unstableme.blogspot.ca/2009/01/difference-between-awk-nr-and-fnr.html
http://www.unix.com/shell-programming-scripting/46931-awk-different-between-nr-fnr.html
答案 3 :(得分:0)
当您想要POSIX兼容版本时,最好的方法是:
(FNR == 1) { FS=":"; $0=$0 }
这表明,如果文件记录号(FNR
)等于1,我们将重置字段分隔符FS
。但是,您还需要重新解析$0
并重置所有其他字段的值和NF
内置变量。
当且仅当记录分隔符(BEGINFILE
)保持不变时,这等效于GNU awk 4.x RS
。