如何将 CSV 文件的列拆分为单独的文件?

如何将 CSV 文件的列拆分为单独的文件?

我有 csv 文件,list.csv如下所示,

Pcissicola19,cissicola39,12xbauhiniae
BGDHLHFA_02833,DGDFDEGP_00879,POPGJMOL_04119
BGDHLHFA_01427,DGDFDEGP_03106,POPGJMOL_01558
BGDHLHFA_01618,DGDFDEGP_02529,POPGJMOL_04348
BGDHLHFA_01349,DGDFDEGP_02811,POPGJMOL_04175
BGDHLHFA_01734,DGDFDEGP_04039,POPGJMOL_04234
BGDHLHFA_00509,DGDFDEGP_02546,POPGJMOL_00085
BGDHLHFA_04577,DGDFDEGP_04242,POPGJMOL_00124

我需要将所有列(每列的第一个字段除外)单独打印到由每列的第一个字段命名的新文件中。预期输出如下:

Pcissicola19.txt

BGDHLHFA_02833
BGDHLHFA_01427
BGDHLHFA_01618
BGDHLHFA_01349
BGDHLHFA_01734
BGDHLHFA_00509
BGDHLHFA_04577

西西科拉39.txt

DGDFDEGP_00879
DGDFDEGP_03106
DGDFDEGP_02529
DGDFDEGP_02811
DGDFDEGP_04039
DGDFDEGP_02546
DGDFDEGP_04242

12x紫荆花.txt

POPGJMOL_04119
POPGJMOL_01558
POPGJMOL_04348
POPGJMOL_04175
POPGJMOL_04234
POPGJMOL_00085
POPGJMOL_00124

我可以使用以下命令打印每一列 awk -F "," '{print $1}' list.csv,但在基于第一个字段保存文件并删除所有新文件中的第一个字段方面,它没有达到我的目的。请帮助我使该过程自动化。先感谢您。

答案1

awk -F, 'NR==1{ split($0, tmp, ","); next }
              { for(col=1; col<=NF; col++){ print $col >>tmp[col]; close(tmp[col])} }' infile

NR==1{ split($0, tmp, ","); next };NR在哪里awk代表总数数量到目前为止读取/看到的记录;所以对于第一行NR会的1,我们正在检查它NR==1,如果它是第一行,那么它的后面的块将被执行,我们这样做分裂()将该行分成由逗号分隔的片段,并将这些片段存储在 array 中tmp。并读取next行;

在第二个块中,我们循环数量F当前输入记录中的字段,并将相应的列打印(附加)到数组$col中的相关文件名中,tmp其中钥匙与该列号相同。

答案2

如果您有足够多的列数,超出了系统允许进程一次打开的最大值(或者任何 awk,如果少于该数),则使用 GNU awk 来管理大量打开的文件:

$ cat tst.awk
BEGIN { FS="," }
NR==1 {
    for (i=1; i<=NF; i++) {
        out[i] = $i ".txt"
    }
    next
}
{
    for (i=1; i<=NF; i++) {
        print $i > out[i]
    }
}

$ awk -f tst.awk list.csv

$ head *.txt
==> 12xbauhiniae.txt <==
POPGJMOL_04119
POPGJMOL_01558
POPGJMOL_04348
POPGJMOL_04175
POPGJMOL_04234
POPGJMOL_00085
POPGJMOL_00124

==> Pcissicola19.txt <==
BGDHLHFA_02833
BGDHLHFA_01427
BGDHLHFA_01618
BGDHLHFA_01349
BGDHLHFA_01734
BGDHLHFA_00509
BGDHLHFA_04577

==> cissicola39.txt <==
DGDFDEGP_00879
DGDFDEGP_03106
DGDFDEGP_02529
DGDFDEGP_02811
DGDFDEGP_04039
DGDFDEGP_02546
DGDFDEGP_04242

否则使用任意 awk 处理任意数量的列:

$ cat tst.awk
BEGIN { FS="," }
NR==1 {
    for (i=1; i<=NF; i++) {
        out[i] = $i ".txt"
        printf "" > out[i]
        close(out[i])
    }
    next
}
{
    for (i=1; i<=NF; i++) {
        print $i >> out[i]
        close(out[i])
    }
}

答案3

或者用bashandcuttr

#!/bin/bash

id=0
while read filename; do
  id=$((id+1))
  tail -n +2 list | cut -d"," -f $id >> "$filename"
done < <(head -1 list.csv | tr "," "\n")

答案4

  • 可以组合使用巴什awk:

    for n in 1 2 3; do awk -F "," "{if (NR!=1) {print \$$n}}" list.scv > $(awk -F "," "{if (NR==1) {print \$$n}}" list.scv) ; done
    
  • 例子: 在此输入图像描述

相关内容