许多人通过一次发布AWK多个输入文件的以下解决方案非常有帮助:
$ awk 'FNR==NR{a[$1]=$2 FS $3;next}{ print $0, a[$1]}' file2 file1
这很好用,但我想知道我是否有人可以向我解释原因?我发现AWK语法有点难以掌握,希望有人不介意为我打破代码片段。
答案 0 :(得分:64)
awk 'FNR==NR{a[$1]=$2 FS $3;next}
这里我们处理第一个输入(file2)。比方说,FS是空格,我们建立一个数组(a
),索引是column1,值是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
检查的技巧。
答案 1 :(得分:11)
我在Google上发现了这个问题/答案,它似乎指的是在另一个问题(How to merge two files using 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的两个文件,其中包含以下行:
TEST1:
line one
line two
line three
TEST2:
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的力量!
答案 2 :(得分:1)
前一段时间,我偶然发现了一个很好的解决方案,可以一次处理多个文件。方法是使用以下方法将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
将保留最后一行的位置。
它具有更多的代码,但是如果您想要更复杂的数据处理,我认为这是更好的方法。此外,以前的方法会按顺序处理输入,因此,如果您需要同时进行一些依赖于两个文件中数据的计算,则将无法执行此操作,并且使用此方法,您可以对两个文件进行所有操作。>