我正在使用 awk 合并多个 (>3) 个文件,我想保留标题。我发现以前的帖子完全符合我的需要,但我不太明白发生了什么。我希望有人可以引导我完成它,以便我可以从中学习! (我尝试对原始帖子发表评论,但没有足够的声誉)
这段代码
awk '{a[FNR]=((a[FNR])?a[FNR]FS$2:$0)}END{for(i=1;i<=FNR;i++) print a[i]}' f*
根据需要转换输入文件。请参阅下面的示例表。
输入文件:
文件1.txt:
id value1
a 10
b 30
c 50
文件2.txt:
id value2
a 90
b 30
c 20
文件3.txt:
id value3
a 0
b 1
c 25
期望的输出
合并.txt:
id value1 value2 value3
a 10 90 0
b 30 30 1
c 50 20 25
再一次,这是代码
awk '{a[FNR]=((a[FNR])?a[FNR]FS$2:$0)}END{for(i=1;i<=FNR;i++) print a[i]}' f* > merge.txt
我无法理解代码的第一部分 {a[FNR]=((a[FNR])?a[FNR]FS$2:$0)}
,但可以理解在代码的第二部分循环。
我认为在代码的第一部分中,正在建立一个数组。代码遍历并检查第一列 id
上的匹配记录,如果匹配则附加第二列 ($2
) value
并打印整个记录 ($0
)。
但是...我不明白开头的语法。何时确定第一列 id
在所有三个文件中都相同并且只添加第二列?
最佳答案
该代码有错误且不必要地复杂,请改用此代码:
$ awk 'NR==FNR{a[FNR]=$0; next} {a[FNR] = a[FNR] OFS $2} END{for (i=1;i<=FNR;i++) print a[i]}' file1 file2 file3
id value1 value2 value3
a 10 90 0
b 30 30 1
c 50 20 25
如果您愿意,将输出通过管道传输到列 -t 以进行对齐:
$ awk 'NR==FNR{a[NR]=$0;next} {a[FNR] = a[FNR] OFS $2} END{for (i=1;i<=FNR;i++) print a[i]}' file1 file2 file3 | column -t
id value1 value2 value3
a 10 90 0
b 30 30 1
c 50 20 25
如果您需要关闭 id
(例如,因为它们在文件中不同),那么它会是:
$ awk '
BEGIN { OFS="\t" }
!($1 in a) { ids[++numIds]=$1 }
{ a[$1][ARGIND]=$2 }
END {
for (i=1;i<=numIds;i++) {
id = ids[i]
printf "%s%s", id, OFS
for (j=1;j<=ARGIND;j++) {
printf "%s%s", a[id][j], (j<ARGIND ? OFS : ORS)
}
}
}
' file1 file2 file3 | column -s$'\t' -t
id value1 value2 value3
a 10 90 0
b 30 30 1
c 50 25
x 20
最后一个脚本将 GNU awk 用于多维数组,只是将输入文件 2 中的 c
更改为 x
以对其进行测试。
如果您有任何问题,请随时提出,但我认为代码非常清楚。
关于bash - 有人可以通过这个 awk 代码来合并多个文件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43455113/