【问题标题】:Adding columns to a csv table with AWK from multiple files使用 AWK 从多个文件将列添加到 csv 表
【发布时间】:2017-11-22 04:22:00
【问题描述】:

我希望通过使用 AWK 从多个文件中获取值来构建一个 csv 表。我让它与两个文件一起工作,但我无法将它扩展到那个范围之外。我目前正在获取第二个文件的输出,并附加第三个文件,依此类推。

这里是示例文件:

#file1  #file2  #file3  #file4
100     45      1       5
200     23      1       2
300     29      2       1
400     0       1       2
500     74      4       5

这是目标:

#data.csv
1,100,45,1,5
2,200,23,1,2
3,300,29,2,1
4,400,0,1,2
5,500,74,4,5

这就是我的工作:

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

结果:

1, 100, 45
2, 200, 23
3, 300, 29
4, 400, 0
5, 500, 74

但是当我尝试让它在 3 个或更多文件上工作时,像这样:

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

我得到这个输出:

1, 100, 45
2, 200, 23
3, 300, 29
4, 400, 0
5, 500, 74
1, 100, 1 
2, 200, 1 
3, 300, 2
4, 400, 1
5, 500, 4

在第一列中,行数重新开始,第二列也重复第一个文件。在第三列中,它将第三个和后续文件添加为新行,我希望这些应该添加为列。不需要新行。

任何帮助将不胜感激。我从 Stack Exchange 学到了我的大部分 AWK,我知道我在这里缺少一些基本的东西。谢谢,

【问题讨论】:

    标签: bash awk


    【解决方案1】:

    正如已经回答的那样,您可以使用paste。要使用逗号分隔的行号获得准确的输出,您可以这样做

    paste -d, file{1..4} | nl -s, -w1
    
    • -s, 将数字分隔符设置为逗号(默认为制表符)。
    • -w1 设置数字宽度,所以没有初始空格(因为默认更大)

    awk 的另一种解决方案

    awk    '{a[FNR]=a[FNR] "," $0} 
        END {for (i=1;i<=length(a);i++) print i a[i]}' file{1..4}
    

    【讨论】:

    • 这两个都是很好的解决方案。使用这个。
    • 注意区分{1..4}[1-4];如果缺少任何文件,前者会抱怨,后者会处理那里的任何文件。
    • @thanasisp 这些都很棒!我不知道粘贴命令。
    • -s, 标志给它行号,但只有一个数字。在 9 之后循环回到 0。如果我使用 -s,它会正确地给我行号,但会添加另一个标志。 8,477,3461 9,3474,6100 0,471,6602 1,3662,3628 awk 的例子也很棒。但是,有没有办法让行正确排序?它们的编号是正确的,但行变得混乱。请参见下面 23 行表的前 5 行示例。 22,485,6871,6183,465,3954 2,458,3178,2621,477,707 23,951,5063,3163,476,707 3,454,4128,2323,462,1009 4,454,3715,2873,447,666 谢谢!
    【解决方案2】:

    为什么不使用粘贴,然后简单地为每一行编号:-

    paste -d"," file1 file2 file3 file4
    100,45,1,5
    200,23,1,2
    300,29,2,1
    400,0 ,1,2
    500,74,4,5
    

    【讨论】:

      【解决方案3】:

      针对可变数量文件的awk 解决方案:

      awk '{ !line[FNR] && line[FNR]=FNR; line[FNR]=line[FNR]","$0 }
           END { for (i=1; i<=length(line); i++) print line[i] }' file1 file2 ... fileN
      

      例如:

      $ awk '{ !line[FNR] && line[FNR]=FNR; line[FNR]=line[FNR]","$0 }
            END { for (i=1; i<=length(line); i++) print line[i] }' \
            <(seq 1 5) <(seq 11 15) <(seq 21 25) <(seq 31 35)
      1,1,11,21,31
      2,2,12,22,32
      3,3,13,23,33
      4,4,14,24,34
      5,5,15,25,35
      

      【讨论】:

        【解决方案4】:

        这是一个适合初学者的解决方案。如果您需要在输入过程中操作数据,您可以清楚地看到正在读取哪个文件。
        ARGIND 是 gawk 特定的。它告诉我们正在处理哪个文件。我们从file1file2 填充两个数组ab,然后在处理file3 时打印您想要的输出。

        awk '
        ARGIND == 1 { a[FNR] = $0 ; next }
        ARGIND == 2 { b[FNR] = $0 ; next }
        ARGIND == 3 { print FNR "," a[FNR] "," b[FNR] "," $0 }
        ' file1 file2 file3
        

        输出:

        1,100,45,1
        2,200,23,1
        3,300,29,2
        4,400,0,1
        5,500,74,4
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-01-11
          • 2022-07-07
          • 2013-10-11
          • 1970-01-01
          • 2023-02-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多