我有 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
或者用bash
andcut
和tr
#!/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")