许多人通过发布以下解决方案来一次对多个输入文件进行 AWK 处理非常有帮助:
$ awk 'FNR==NR{a[$1]=$2 FS $3;next}{ print $0, a[$1]}' file2 file1
这很好用,但我想知道是否有人可以向我解释为什么?我发现 AWK 语法有点难以掌握,并希望有人不介意为我分解代码片段。
许多人通过发布以下解决方案来一次对多个输入文件进行 AWK 处理非常有帮助:
$ awk 'FNR==NR{a[$1]=$2 FS $3;next}{ print $0, a[$1]}' file2 file1
这很好用,但我想知道是否有人可以向我解释为什么?我发现 AWK 语法有点难以掌握,并希望有人不介意为我分解代码片段。
awk 'FNR==NR{a[$1]=$2 FS $3;next}
这里我们处理第一个输入(file2)。比如说,FS是空间,我们a
向上构建一个array(),索引是column1,value是column2 " " column3
手段FNR==NR and next
,这部分代码只对file2起作用。你可以看看什么是 NR 和 FNR
{ print $0, a[$1]}' file2 file1
当NR != FNR
需要处理第二个输入时,file1. 这里我们打印file1的行,以column1为索引,找出array(a) print中的值。换句话说,file1 和 file2 在两个文件中都由 column1 连接。
对于 NR 和 FNR,很快,
1st input has 5 lines
2nd input has 10 lines,
NR would be 1,2,3...15
FNR would be 1...5 then 1...10
你看到了FNR==NR
检查的把戏。
我在 Google 上找到了这个问题/答案,它似乎是指在另一个问题(如何使用 AWK 合并两个文件?)中找到的一个非常具体的数据集。下面是我一直在寻找的答案(我想大多数人都会这样),即简单地使用 AWK 连接来自两个不同文件的每一行。尽管您可能可以使用一些 UNIX 实用程序,例如join或paste,但如果您想要的输出不同,AWK 显然会更加灵活和强大,通过使用if语句或更改OFS(根据实用程序的不同,这可能更难做到;见下文)例如,以更具表现力的方式更改输出(对于 shell 脚本编写者来说,这是一个重要的考虑因素。)
对于简单的逐行连接:
awk 'FNR==NR { a[FNR""] = $0; next } { print a[FNR""], $0 }' file1 file2
这通过使用隐式类型转换来模拟数字索引数组(AWK 仅具有关联数组)的功能。它相对具有表现力且易于理解。
使用两个名为 test1 和 test2 的文件,其中包含以下行:
测试1:
line one
line two
line three
测试2:
line four
line five
line six
我得到这个结果:
line one line four
line two line five
line three line six
根据您希望如何连接输出中的列之间的值,您可以选择适当的输出字段分隔符。这是一个用省略号 (...) 分隔列的示例:
awk 'BEGIN { OFS="..."} FNR==NR { a[(FNR"")] = $0; next } { print a[(FNR"")], $0 }' test1 test2
产生这个结果:
line one...line four
line two...line five
line three...line six
我希望至少这能激发你们所有人利用 AWK 的力量!
不久前,我偶然发现了一个非常好的解决方案来一次处理多个文件。方法是使用以下方法将 AWK 数组中的文件保存在内存中:
FILENAME==ARGV[1] { file2array[FNR] = $0 ; next }
FILENAME==ARGV[2] { file1array[FNR] = $0 ; next }
对于后期数据处理,最好保存行数,所以:
FILENAME==ARGV[1] { file2array[FNR] = $0 ; f2rows = FNR ; next }
FILENAME==ARGV[2] { file1array[FNR] = $0 ; f1rows = FNR ; next }
f2rows
并将f1rows
保持最后一行的位置。
它有更多的代码,但如果你想要更复杂的数据处理,我认为这是更好的方法。此外,以前的方法按顺序处理输入,因此如果您需要同时进行一些依赖于来自两个文件的数据的计算,您将无法做到这一点,而使用这种方法,您可以对两个文件进行所有操作。