例如,假设我运行以下命令:
gawk -f AppendMapping.awk Reference.tsv TrueInput.tsv
假设文件名会改变。在遍历第一个文件时,我想创建一个映射。
map[$16]=$18
在遍历第二个文件时,我想使用映射。
print $1, map[$2]
实现这种行为的最佳方法是什么(即每个输入文件的不同行为)?
您可能知道NR
存储当前行号;正如您可能知道或可能不知道的那样,它是累积的 - 它不会在文件之间重置。FNR
另一方面,特定于文件,因此您可以使用这两个来查看您是否在第一个文件中(第二个之后您需要保留自己的计数器)。
# In case you want to keep track of the file number
FNR == 1 { fileno++ }*emphasized text*
NR == FNR {
# First file
}
NR != FNR {
# Second or later file
}
您也可以getline
在BEGIN
块中使用手动循环遍历它。
BEGIN {
file = ARGV[1]
while(getline < file) {
# Process line
}
delete ARGV[1]
}
Gawk 版本 4 和更高版本提供特殊BEGINFILE
(and ENDFILE
) 块以及通常的BEGIN
andEND
块。使用它们来设置您改变代码行为的标志。
回想一下,模式可以包括与变量的比较,因此您可以直接根据标志的值选择模式。
手册页说:
对于每个输入文件,如果存在 BEGINFILE 规则,gawk 会在处理文件内容之前执行相关代码。类似地,gawk 在处理完文件后执行与 ENDFILE 相关的代码。
这可能对您有用:
seq 5 >/tmp/a
seq 100 105 >/tmp/b
awk 'FILENAME==ARGV[1]{print FILENAME,$0};FILENAME==ARGV[2]{print $0,FILENAME}' /tmp/{a,b}
/tmp/a 1
/tmp/a 2
/tmp/a 3
/tmp/a 4
/tmp/a 5
100 /tmp/b
101 /tmp/b
102 /tmp/b
103 /tmp/b
104 /tmp/b
105 /tmp/b
所以通过在命令行中结合FILENAME
where ARGV[n]
is n
the nth file,awk
可以有条件地改变单个文件。
NB ARGV[0] 将是awk
命令。