【问题标题】:bash? - combining files into CSVs重击? - 将文件组合成 CSV
【发布时间】:2017-03-15 08:47:06
【问题描述】:

我知道(请参阅here)如果每个文件都包含一个列,您可以使用paste 将多个文件组合成一个.csv 文件

paste -d "," column1.dat column2.dat column3.dat ... > myDat.csv 将导致

myDat.csv

column1,   column2,   column3, ...
c1-1,      c2-1,      c3-1,    ...
c1-2,      c2-2,      c3-2,    ...
...        ...        ...

(没有标签。只是插入它们以使其更具可读性)

如果我有多个测量值怎么办?

例如

file1.dat 的格式为<xvalue> <y1value>

file2.dat 的格式为 <xvalue> <y2avlue>

file3.dat 的格式为 <xvalue> <uvalue> <vvalue>

我最终想要一个类似 csv 的文件

<xvalue>, <y1value>, <y2value>, <empty column>, <uvalue>, <vvalue>

?

我现在如何合并文件?

编辑

请注意,虽然每个文件都已排序(或者如果没有排序,也可以排序),但它们不一定在同一行包含相同的 xvalue。

如果一个文件不具有另一个文件所具有的 xvalue,则其对应的列条目应为空白。

(实际上,我认为删除并非所有文件中都存在的 xvalue 的行也应该有效。)

【问题讨论】:

  • 每个文件都排序了吗?是否会发生 file2.dat 包含不在 file1.dat 中的 xvalue 或相反的情况?
  • @andlrc 对已排序是肯定的(如果不是,在合并文件之前对它们进行排序应该不会太难)。不幸的是,对xvalue 的分歧也是肯定的,

标签: bash csv text data-manipulation


【解决方案1】:

只使用进程替换?

paste -d, > myDat.csv \
  file1.dat \
  <(cut -d' ' -f2 file2.dat) \
  /dev/null \
  <(cut -d' ' -f2,3 file3.dat)

【讨论】:

  • 这假设文件同意 xvalues,不是吗?
  • 确实如此。如果不是这种情况,则必须在内存中缓冲多个文件,然后查找正确的行。
  • 我该怎么做?
【解决方案2】:

您可以使用paste 合并所有文件,然后使用awk 仅打印您想要的列(包括一个空列):

paste file1.dat file2.dat file3.dat | awk -v OFS=', ' '{print $1,$2,$4,"",$6,$7}'

请注意,$3$5 列被排除在 awk 命令之外,因为它们与 $1 列相同(即它们都是 &lt;xvalue&gt;)。

【讨论】:

  • 与上面 andlrc 的回答相同的问题:它假设文件在 xvalues 上达成一致,但不一定是这种情况。
【解决方案3】:

好的,这是我在 Gnu awk 中的解决方案,它试图倾向于成为一个更通用的解决方案,并使用外部工具处理多余的空列。它在 Gnu awk 中,因为它使用多维数组,但也可以很容易地推广到其他 awk。

程序连接期望每个文件的第一个字段作为键列的字段。如果它没有找到要加入的键,它会创建一个新键,并在输出时将不存在的字段输出为空(注意数据文件中的键 x_3x_4x_5)。

首先是数据文件:

$ cat file[123].dat             # 3 files, separated by empty lines for clarity
x_1 y1_1
x_2 y1_2
x_3 y1_3

x_1 y2_1
x_2 y2_2
x_4 y2_4

x_1 u_1 v_1
x_2 u_2 v_2
x_5 u_5 v_5

还有代码:

$ cat program.awk
BEGIN { OFS=", " }
FNR==1 { f++ }                                # counter of files
{
    a[0][$1]=$1                               # reset the key for every record 
    for(i=2;i<=NF;i++)                        # for each non-key element
        a[f][$1]=a[f][$1] $i ( i==NF?"":OFS ) # combine them to array element
}
END {                                         # in the end
    for(i in a[0])                            # go thru every key
        for(j=0;j<=f;j++)                     # and all related array elements
            printf "%s%s", a[j][i], (j==f?ORS:OFS)
}                                             # output them, nonexistent will output empty

使用和输出:

$ awk -f program.awk \
file1.dat \
file2.dat \
<(grep -h . file[123].dat|cut -d\  -f 1|sort|uniq) \
file3.dat 
x_1, y1_1, y2_1, , u_1, v_1
x_2, y1_2, y2_2, , u_2, v_2
x_3, y1_3, , , 
x_4, , y2_4, , 
x_5, , , , u_5, v_5

file2.dat 之后的空列将生成空字段,该字段通过收集所有键并将它们作为另一个“文件”输入(使用进程替换&lt;())来保持程序更通用:

$ grep -h . file[123].dat|cut -d\  -f 1|sort|uniq
x_1
x_2
x_3
x_4
x_5

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-30
    • 2012-12-08
    • 1970-01-01
    • 2012-01-14
    • 2016-01-09
    相关资源
    最近更新 更多