使用AWK处理来自多个文件的输入

jko*_*vba 58 awk

很多人通过一次发布AWK多个输入文件的以下解决方案非常有帮助:

$ awk 'FNR==NR{a[$1]=$2 FS $3;next}{ print $0, a[$1]}' file2 file1
Run Code Online (Sandbox Code Playgroud)

这很好用,但我想知道我是否有人可以向我解释原因?我发现AWK语法有点难以掌握,希望有人不介意为我打破代码片段.

Ken*_*ent 66

awk 'FNR==NR{a[$1]=$2 FS $3;next}
Run Code Online (Sandbox Code Playgroud)

这里我们处理第一个输入(file2).比方说,FS是空间,我们构建的阵列(a)时,指数是列1,值column2 " " column3FNR==NR and next装置,这部分代码为file2的唯一工作.你可以傻瓜检查NR和FNR是什么

{ print $0, a[$1]}' file2 file1
Run Code Online (Sandbox Code Playgroud)

NR != FNR它的时间来处理第二输入,文件1.这里我们打印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
Run Code Online (Sandbox Code Playgroud)

你看到FNR==NR检查的伎俩.

  • @aerijman 你也可以使用“-”。例如,`seq 5 | awk '...' - file2` (2认同)

小智 12

我在Google上发现了这个问题/答案,它似乎指的是另一个问题中找到的非常具体的数据集(如何使用AWK合并两个文件?).接下来是我正在寻找的答案(我认为大多数人都会这样),即简单地使用AWK连接来自两个不同文件的每一行.虽然您可以使用一些UNIX实用程序(如连接粘贴),但是如果您的所需输出不同,使用if语句或更改OFS(根据实用程序可能更难做),AWK显然更加灵活和强大.例如,以更具表现力的方式改变输出(shell脚本编写者的一个重要考虑因素).

对于简单的逐行连接:

awk 'FNR==NR { a[FNR""] = $0; next } { print a[FNR""], $0 }' file1 file2

这通过使用隐式类型转换来模拟数字索引数组(AWK仅具有关联数组)的功能.它相对富有表现力且易于理解.

使用名为test1和test2的两个文件,其中包含以下行:

测试1:

line one
line two
line three
Run Code Online (Sandbox Code Playgroud)

测试2:

line four
line five
line six
Run Code Online (Sandbox Code Playgroud)

我得到这个结果:

line one line four
line two line five
line three line six
Run Code Online (Sandbox Code Playgroud)

根据您希望如何连接输出中列之间的值,您可以选择适当的输出字段分隔符.这是一个分隔列的省略号(...)示例:

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
Run Code Online (Sandbox Code Playgroud)

我希望至少这能激发你们所有人利用AWK的力量!

  • 如果目标只是并排连接列,则使用`paste`命令非常简单. (5认同)

小智 8

不久前,我偶然发现了一个非常好的解决方案来同时处理多个文件。方法是使用以下方法将AWK数组中的文件保存在内存中:

FILENAME==ARGV[1] {  file2array[FNR] = $0 ; next }
FILENAME==ARGV[2] {  file1array[FNR] = $0 ; next }
Run Code Online (Sandbox Code Playgroud)

对于后期数据处理,最好是保存行数,所以:

FILENAME==ARGV[1] {  file2array[FNR] = $0 ; f2rows = FNR ; next }
FILENAME==ARGV[2] {  file1array[FNR] = $0 ; f1rows = FNR ; next }
Run Code Online (Sandbox Code Playgroud)

f2rowsf1rows将举行最后一排的位置。

它有更多的代码,但如果你想要更复杂的数据处理,我认为这是更好的方法。此外,以前的方法按顺序处理输入,因此如果您需要同时进行一些依赖于来自两个文件的数据的计算,您将无法执行此操作,而使用这种方法,您可以对两个文件执行所有操作。