选择带有排序的列,并使用逗号分隔符 ',' 剪切 csv,忽略带有逗号“text,text”的引号中的数据

选择带有排序的列,并使用逗号分隔符 ',' 剪切 csv,忽略带有逗号“text,text”的引号中的数据

我正在解析一个巨大的 csv 文件,其中包含具有不同参数的行和列。但是,某些字段在包含逗号的引号内包含大量描述。如何选择排序并剪切忽略引号内逗号的列?我尝试添加 quote-comma-quote 作为分隔符,但出现错误(参数无效)或用反斜杠对引号进行转义,但也出现错误。

sort  -k12 -t'","' file

或者

cut -f 12 -d '","' file

文件中的行示例:

"GFYZ01001952.1",99.606,"ASTG2327","PREDICTED: kinesin-like protein NACK1 [Elaeis guineensis]","--","centromeric protein E","Kinesin-like protein NACK1 OS=Arabidopsis thaliana GN=NACK1 PE=1 SV=1","Baculovirus polyhedron envelope protein, PEP, C terminus//Autophagy protein Apg6//Basic region leucine zipper//Protein of unknown function (DUF904)",0.005,3.2,3.5,0.00006

答案1

CSV 是一种结构化文档格式。因此,简单的文本操作工具cut(或sortsed、 或awk,除非数据很简单)不足以安全、方便地处理 CSV 文件(因为字段可能包含嵌入的分隔符和换行符)。相反,最好使用支持 CSV 的处理工具,例如磨坊主( mlr)。

以下 Miller 命令将该文件解析为无标头 CSV 文件,并按第 12 个字段按数字升序对其进行排序:

mlr --csv -N sort -n 12 file

如果 CSV 数据中有标题,请删除该-N选项并使用标​​题名称代替12,例如

mlr --cvs sort -n pvalue file

要提取第 12 列,

mlr --csv -N cut -f 12 file

排序切,也只得到前10个结果,

mlr --csv -N sort -n 12 then cut -f 12 then head -n 10 file

-N再次,如果输入中有标题,请删除并使用字段名称。


随着csvkit工具包,您可以使用它csvsort来获得相同的结果,如下所示:

csvsort -H -c 12 file | tail -n +2

(该tail命令删除生成的标头csvsort),或者,使用输入中的标头,

csvsort -c pvalue file

使用以下命令提取各个字段csvcut

csvcut -H -c 12 file

结合csvsort

csvsort -H -c 12 file | csvcut -c 12 | head -n +2

或者,使用标题,

csvsort -c pvalue file | csvcut -c pvalue

没有csvhead命令,因此必须通过其他方式将结果限制为 10 条记录,可能通过mlr --csv head -n 10.

答案2

使用 GNU awkFPAT可以识别字段:

$ awk -v FPAT='[^,]*|("([^"]|"")*")' '{for (i=1; i<=NF;i++) print i " <" $i ">"}' file
1 <"GFYZ01001952.1">
2 <99.606>
3 <"ASTG2327">
4 <"PREDICTED: kinesin-like protein NACK1 [Elaeis guineensis]">
5 <"--">
6 <"centromeric protein E">
7 <"Kinesin-like protein NACK1 OS=Arabidopsis thaliana GN=NACK1 PE=1 SV=1">
8 <"Baculovirus polyhedron envelope protein, PEP, C terminus//Autophagy protein Apg6//Basic region leucine zipper//Protein of unknown function (DUF904)">
9 <0.005>
10 <3.2>
11 <3.5>
12 <0.00006>

虽然您可以在 gawk 内部执行与您的sortandcut命令相同的操作,但如果您确实想使用这些外部命令,您可以使用 awk 将 ; 分隔的 \n 终止的记录转换为 \n 分隔的 NUL 终止的记录,然后通过管道连接到任何可以处理 NUL 终止输入的工具,然后根据需要再次转换回来,例如使用 GNU awk、剪切和排序:

$ awk -v FPAT='[^,]*|("([^"]|"")*")' -v OFS='\n' -v ORS='\0' '{$1=$1} 1' file |
    cut -z -f 12 -d $'\n'
0.00006$

$ awk -v FPAT='[^,]*|("([^"]|"")*")' -v OFS='\n' -v ORS='\0' '{$1=$1} 1' file |
    sort -z -k 12 -t $'\n' |
    awk -v RS='\0' -v ORS='\n' -F '\n' -v OFS=';' '{$1=$1} 1'
"GFYZ01001952.1";99.606;"ASTG2327";"PREDICTED: kinesin-like protein NACK1 [Elaeis guineensis]";"--";"centromeric protein E";"Kinesin-like protein NACK1 OS=Arabidopsis thaliana GN=NACK1 PE=1 SV=1";"Baculovirus polyhedron envelope protein, PEP, C terminus//Autophagy protein Apg6//Basic region leucine zipper//Protein of unknown function (DUF904)";0.005;3.2;3.5;0.00006

使用 awk 高效解析 csv 的最稳健方法是什么了解更多信息。

相关内容