使用Awk从分隔文件中提取特定列

use*_*432 33 unix csv awk

对不起,如果这太基础了.我有一个csv文件,其中列有一个标题行(v1,v2等).我知道要提取第1列和第2列,我必须这样做:awk -F "," '{print $1 "," $2}' infile.csv > outfile.csv.但是,如果我必须提取1到10,20到25和30,33列呢?作为附录,有没有办法直接提取标题名称而不是列号?

Cli*_*iff 53

我不知道是否可以在awk中执行范围.你可以做一个for循环,但你必须添加处理来过滤掉你不想要的列.这样做可能更容易:

awk -F, '{OFS=",";print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$20,$21,$22,$23,$24,$25,$30,$33}' infile.csv > outfile.csv
Run Code Online (Sandbox Code Playgroud)

需要考虑的其他事情 - 这更快更简洁:

cut -d "," -f1-10,20-25,30-33 infile.csv > outfile.csv
Run Code Online (Sandbox Code Playgroud)

至于问题的第二部分,我可能会在perl中编写一个脚本,它知道如何处理标题行,从stdin或文件中解析列名,然后进行过滤.它可能是我想要用于其他事情的工具.虽然我确信可以做到,但我不确定是否会做一个班轮.

  • 请注意,在带引号字符串的CSV文件的一般情况下,您可以在数据字段中使用非分隔符号,这将导致剪切和awk解决方案失败. (3认同)
  • 非常感谢.我想,切割是我需要的.这不适用于标题,任何机会? (2认同)

stu*_*eek 14

正如@Tom所提到的,cut和awk方法实际上不适用于带引号字符串的CSV.另一种方法是python模块,它提供命令行工具csvfilter.它像剪切一样工作,但正确处理CSV列引用:

csvfilter -f 1,3,5 in.csv > out.csv
Run Code Online (Sandbox Code Playgroud)

如果你有python(你应该),你可以像这样安装它:

pip install csvfilter
Run Code Online (Sandbox Code Playgroud)

请注意,csvfilter中的列索引以0开头(与awk不同,后者以$ 1开头).更多信息,访问https://github.com/codeinthehole/csvfilter/