【问题标题】:How to add data beside each other in a csv file如何在 csv 文件中并排添加数据
【发布时间】:2013-10-24 13:54:00
【问题描述】:

如果我有 3 个 csv 文件,并且我想将数据全部合并为一个,但彼此并排,我该怎么做?例如:

初始合并文件:

,,,,,,,,,,,,

文件 1:

20,09/05,5694
20,09/06,3234
20,09/08,2342

文件 2:

20,09/05,2341
20,09/06,2334
20,09/09,342

文件 3:

20,09/05,1231
20,09/08,3452
20,09/10,2345
20,09/11,372

最终合并文件:

09/05,5694,,,09/05,2341,,,09/05,1231
09/06,3234,,,09/06,2334,,,09/08,3452
09/08,2342,,,09/09,342,,,09/10,2345
,,,,,,,,09/11,372

基本上,每个文件中的数据都会进入合并文件的特定列。 我知道 awk 函数可以用于此,但我不知道如何开始

编辑:仅打印每个文件的第 2 列和第 3 列。我用它来打印第二列和第三列:

awk -v f="${i}" -F, 'match ($0,f) { print $2","$3 }' file3.csv > d$i.csv

但是,例如,file1 和 file2 在该行中为空,该行的数据将向左移动。所以我想出了这个来解释这种转变:

awk -v x="${i}" -F, 'match ($0,x) { if ($2='/NULL') { print "," }; else { print $2","$3}; }' alld.csv > d$i.csv

【问题讨论】:

    标签: linux csv sed awk


    【解决方案1】:

    将 GNU awk 用于 ARGIND:

    $ gawk '{ a[FNR,ARGIND]=$0; maxFnr=(FNR>maxFnr?FNR:maxFnr) }
        END {
            for (i=1;i<=maxFnr;i++) {
                for (j=1;j<ARGC;j++)
                    printf "%s%s", (j==1?"":",,,"), (a[i,j]?a[i,j]:",")
                print ""
            }
        }
    ' file1 file2 file3
    09/05,5694,,,09/05,2341,,,09/05,1231
    09/06,3234,,,09/06,2334,,,09/08,3452
    09/08,2342,,,09/09,342,,,09/10,2345
    ,,,,,,,,09/11,372
    

    如果您没有 GNU awk,只需添加一个初始行,即 FNR==1{ARGIND++}

    每个请求的注释版本:

    $ gawk '
        { a[FNR,ARGIND]=$0; # Store the current line in a 2-D array `a` indexed by
                            # the current line number `FNR` and file number `ARGIND`.
    
          maxFnr=(FNR>maxFnr?FNR:maxFnr)    # save the max FNR value
        }
        END{
            for (i=1;i<=maxFnr;i++) {  # Loop from 1 to max number of fields
                                       # seen across all files and for each:
                for (j=1;j<ARGC;j++)     # Loop from 1 to total number of files parsed and:
                    printf "%s%s",         # Print 2 strings, specifically:
                       (j==1?"":",,,"),      # A field separator - empty if were printing
                                             # the first field, three commas otherwise.
                       (a[i,j]?a[i,j]:",")   # The value stored in the array if it was
                                             # present in the files, a comma otherwise.
                print ""                   # Print a newline
            }
        }
    ' file1 file2 file3
    

    我最初使用数组 fnr[FNR] 来跟踪 FNR 的最大值,但恕我直言,这有点模糊,它有一个缺陷,如果没有行有第二个字段,那么 for (i=1;i in fnr;i++) 在 @ 987654327@ 部分将在进入第三场之前退出。

    【讨论】:

    • 是的!这行得通,谢谢你..你能解释一下吗?我了解嵌套循环,但这些术语是什么意思,到底发生了什么?
    • 我对其进行了一些清理并添加了一个注释版本。如果这符合您的要求,请记住单击它旁边的复选标记,这样其他人就不会浪费时间也尝试解决它
    • 不幸的是,我不太精通这种语言——一般来说,“:”和“?”是什么意思?什么意思?
    • 这是一个三元运算符,在很多语言中都很常见。请参阅en.wikipedia.org/wiki/Ternary_operation 或谷歌搜索。 (a?b:c) 表示if (a) then b else c,所以x=(a?b:c) 表示if (a) then x=b else x=c
    【解决方案2】:

    paste 就是为此完成的:

    $ paste -d";" f1 f2 f3 | sed 's/;/,,,/g'
    09/05,5694,,,09/05,2341,,,09/05,1231
    09/06,3234,,,09/06,2334,,,09/08,3452
    09/08,2342,,,09/09,342,,,09/10,2345
    ,,,,,,09/11,372
    

    请注意,单独的paste 只会输出一个逗号:

    $ paste -d, f1 f2 f3
    09/05,5694,09/05,2341,09/05,1231
    09/06,3234,09/06,2334,09/08,3452
    09/08,2342,09/09,342,09/10,2345
    ,,09/11,372
    

    所以要拥有多个分隔符,我们可以使用另一个分隔符,例如 ;,然后用 sed 替换为 ,,,

    $ paste -d";" f1 f2 f3 | sed 's/;/,,,/g'
    09/05,5694,,,09/05,2341,,,09/05,1231
    09/06,3234,,,09/06,2334,,,09/08,3452
    09/08,2342,,,09/09,342,,,09/10,2345
    ,,,,,,09/11,372
    

    【讨论】:

    • 简单可爱的解决方案,+1
    • 这在大多数情况下都有效。但是,当我尝试将其合并到我的程序中时,它并不能很好地工作(我不知道这是否是一个新线程,因为它们是相关的,但是..)我的 csv 有 3 列,我只打印出第 2 列和第 3 列,我能够实现这一点,但是当一个文件中的一列为空(比下一个文件中的列更早结束)时,它会弄乱整个格式......我想出了这个。但它给出了一个错误: awk -v x="${i}" -F, 'match ($0,x) { if ($2='/NULL') { print "," };否则 { 打印 $2","$3}; }' all.csv > ul$i.csv
    • @user2883071 请使用示例输入更新您的问题,以便我改进解决方案。另请注意,这可能会有所帮助:unix.stackexchange.com/questions/16443/…
    【解决方案3】:

    使用pr

    $ pr -mts',,,' file[1-3]
    09/05,5694,,,09/05,2341,,,09/05,1231
    09/06,3234,,,09/06,2334,,,09/08,3452
    09/08,2342,,,09/09,342,,,09/10,2345
    ,,,,,,09/11,372
    

    【讨论】:

      猜你喜欢
      • 2018-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多