Text-Processing

如何將 CSV 文件的列拆分為單獨的文件?

  • February 23, 2021

我有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

cissicola39.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,但就基於第一個欄位保存文件和刪除所有新文件中的第一個欄位而言,它不符合我的目的。請幫我自動化這個過程。先感謝您。

如果您有超過 15 列(如果少於 15 列,則使用任何 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])
   }
}
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 }; 其中NRawk中表示到目前為止讀取/看到的記錄總數**;所以對於第一行NR將是,我們正在檢查它,如果它是第一行,那麼它的下一個塊將被執行,我們將該行split()分成由逗號分隔的片段並將這些片段儲存在 array 中。和讀線;1NR==1*,``tmp``next

在第二個塊中,我們循環目前輸入記錄中的欄位數,並將相應的列列印(附加)到數組中的相關文件名中,其中與該列號相同***。***$col``tmp

引用自:https://unix.stackexchange.com/questions/635139