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

Unix 使用Awk从分隔文件中提取特定列,unix,csv,awk,Unix,Csv,Awk,抱歉,如果这太基本了。我有一个csv文件,其中列有一个标题行(v1、v2等)。我知道要提取第1列和第2列,我必须做:awk-F“,“{print$1”,“$2}”infle.csv>outfile.csv。但是如果我必须提取,比如说,第1列到第10列,第20列到第25列,第30列和第33列,该怎么办?作为附录,是否有任何方法可以直接使用标题名而不是列号进行提取?我不知道是否可以在awk中进行范围提取。可以执行for循环,但必须添加处理来过滤掉不需要的列。这样做可能更容易: awk -F, '{O

抱歉,如果这太基本了。我有一个csv文件,其中列有一个标题行(v1、v2等)。我知道要提取第1列和第2列,我必须做:
awk-F“,“{print$1”,“$2}”infle.csv>outfile.csv
。但是如果我必须提取,比如说,第1列到第10列,第20列到第25列,第30列和第33列,该怎么办?作为附录,是否有任何方法可以直接使用标题名而不是列号进行提取?

我不知道是否可以在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
<>其他要考虑的事情——而且这个更快更简洁:

cut -d "," -f1-10,20-25,30-33 infile.csv > outfile.csv

至于问题的第二部分,我可能会用perl编写一个脚本,知道如何处理标题行,解析stdin或文件中的列名,然后进行过滤。这可能是一个工具,我想为其他事情。我不确定是否使用一行程序,尽管我确信这是可以做到的。

其他语言对于字段编号的范围有捷径,但不是awk,您将不得不编写代码,因为您担心;-)

awk中没有将字段名用作列说明符的直接函数


我希望这会有所帮助。

您可以使用for循环来处理带有$I的字段:


ls-l | awk'{for(i=3;i其他人已经回答了您先前的问题。为此:

作为附录,是否有任何方法可以直接使用标题名而不是列号进行提取

我还没有尝试过,但是您可以将每个头的索引存储在一个散列中,然后使用该散列获取其索引

for(i=0;i<$NF;i++){
    hash[$i] = i;
}

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

csvfilter -f 1,3,5 in.csv > out.csv
如果您有python(您应该这样做),您可以像这样简单地安装它:

pip install csvfilter
请注意,csvfilter中的列索引从0开始(与awk不同,awk从$1开始)。有关详细信息,请访问是一组unix命令行工具,用于处理具有标题行的csv文件。下面是一个按名称从文件中提取列的示例
test.csv:

name,sex,house_nr,height,shoe_size
arthur,m,42,181,11.5
berta,f,101,163,8.5
chris,m,1333,175,10
don,m,77,185,12.5
elisa,f,204,166,7
然后
tblmap-k name,height test.csv

name,height
arthur,181
berta,163
chris,175
don,185
elisa,166
如果Perl是一个选项:

perl-F,-lane'print join',“,@F[0,1,2,3,4,5,6,7,8,9,19,20,21,22,23,24,29,32]”

-a
自动将行拆分为
@F
字段数组。索引从0开始(而不是像awk中的1)
-F,
字段分隔符为

如果您的CSV文件中包含引号内的逗号,则完全成熟的CSV解析器(如Perl的
Text::CSV_XS
)是专门为处理这种奇怪情况而构建的

perl-MText::CSV_XS-lne'BEGIN{$CSV=Text::CSV_XS->new()}if($CSV->parse($))){@f=$CSV->fields();print(join“,”,@f[0,1,2,3,4,5,6,7,8,9,19,20,21,22,23,24,29,32])


我在这里的回答中提供了更多的解释:

没有使用awk,但我能够做到这一点的最简单方法就是使用。我还有其他使用csvtool的用例,如果引号或分隔符出现在列数据本身中,它可以适当地处理它们

csvtool format '%(2)\n' input.csv
csvtool format '%(2),%(3),%(4)\n' input.csv

将2替换为列号将有效地提取您要查找的列数据。

非常感谢。我想剪切是我所需要的。这可能不适用于标题?我只是想建议
Cut
,但克里夫先到了这里。请注意,在带有引号字符串的CSV文件的一般情况下,您可以使用非字符串-在数据字段中分隔逗号,这将导致cut&awk解决方案失败。确实如此。感谢您的确认:-(
name,sex,house_nr,height,shoe_size
arthur,m,42,181,11.5
berta,f,101,163,8.5
chris,m,1333,175,10
don,m,77,185,12.5
elisa,f,204,166,7
name,height
arthur,181
berta,163
chris,175
don,185
elisa,166
csvtool format '%(2)\n' input.csv
csvtool format '%(2),%(3),%(4)\n' input.csv