对不起,如果这太基础了。我有一个csv文件,其中列有一个标题行(v1,v2等)。我知道要提取第1列和第2列,我必须这样做:awk -F "," '{print $1 "," $2}' infile.csv > outfile.csv
。但是,如果我必须提取1到10,20到25和30,33列呢?作为附录,有没有办法直接使用标题名称而不是列号来提取?
答案 0 :(得分:52)
我不知道是否可以在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或文件中解析列名,然后进行过滤。它可能是我想要用于其他事情的工具。我不确定在一个班轮上做什么,虽然我确信它可以做到。
答案 1 :(得分:13)
如@Tom所述,剪切和awk方法实际上不适用于带引号字符串的CSV。另一种方法是python模块,它提供命令行工具csvfilter。它像剪切一样工作,但正确处理CSV列引用:
csvfilter -f 1,3,5 in.csv > out.csv
如果你有python(你应该),你可以像这样安装它:
pip install csvfilter
请注意csvfilter中的列索引以0开头(与awk不同,后者以$ 1开头)。有关详情,请访问https://github.com/codeinthehole/csvfilter/
答案 2 :(得分:3)
其他语言对字段数字的范围有快捷方式,但不是awk,你必须编写代码作为你的恐惧; - )
awk -F, 'BEGIN {OFS=","} { print $1, $2, $3, $4 ..... $30, $33}' infile.csv > outfile.csv
awk中没有直接函数将字段名称用作列说明符。
我希望这会有所帮助。
答案 3 :(得分:3)
其他人已回答您之前的问题。为此:
作为附录,有没有办法直接使用标题名称而不是列号来提取?
我没有尝试过,但您可以将每个标头的索引存储在一个哈希中,然后使用该哈希值来获取其索引。
for(i=0;i<$NF;i++){
hash[$i] = i;
}
然后,使用它:
j = hash["header1"];
print $j;
答案 4 :(得分:2)
您可以使用for循环来处理 $ i 的字段:
ls -l | awk '{for(i=3 ; i<8 ; i++) {printf("%s\t", $i)} print ""}'
答案 5 :(得分:1)
Tabulator是一组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
答案 6 :(得分:0)
If Perl is an option:
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
autosplits line into @F
fields array. Indices start at 0 (not 1 as in awk)
-F,
field separator is ,
If your CSV file contains commas within quotes, fully fledged CSV parsers such as Perl's Text::CSV_XS
are purpose-built to handle that kind of weirdness.
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])}'
I provided more explanation within my answer here: parse csv file using gawk
答案 7 :(得分:0)
不使用awk,但我能够完成此操作的最简单方法就是使用csvtool。我还有其他用例也可以使用csvtool,如果它们出现在列数据本身内,它可以适当地处理引号或分隔符。
csvtool format '%(2)\n' input.csv
csvtool format '%(2),%(3),%(4)\n' input.csv
用列号替换2将有效地提取您要查找的列数据。