bash - 有人可以通过这个 awk 代码来合并多个文件吗?

标签 bash awk gawk

我正在使用 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/

相关文章:

text - 连接文本文件的两列

linux - 从 bash 脚本作为 cronjob 启动 bash 脚本

linux - 条件中的 Bash 脚本通配符

linux - 如何使用awk生成3个总和为60的自然数

performance - 如何在不使用 echo 的情况下 awk 或 grep 变量?

linux - 从 shell 脚本更新文件中的计数器

git - 如何在 commit-msg 钩子(Hook)中捕获 git commit 消息?

Bash getopts 删除最后一个参数

sed - 使用 sed 或 awk 删除行

linux - 我应该始终使用 GAWK 而不是 AWK 吗?