我只是Perl的初学者,在使用Perl脚本过滤列时需要一些帮助。 我在文件中有大约10个以逗号分隔的列,我需要在该文件中保留5列,并从该文件中删除所有其他列。我们如何实现这一目标?
非常感谢任何人的帮助。
欢呼声, 尼尔
答案 0 :(得分:20)
查看Text::CSV(或Text::CSV_XS)来解析Perl中的CSV文件。它可以在CPAN上获得,或者如果您使用的是Linux或其他类Unix操作系统,则可以通过包管理器获取它。在Ubuntu中,包名为libtext-csv-perl。
它可以处理引用的字段之类的情况,因为它们包含逗号,这是简单的拆分命令无法处理的内容。
答案 1 :(得分:6)
CSV是一种定义不明确的复杂格式(引号,逗号和空格的奇怪问题)。寻找可以为您处理细微差别的a library,并为您提供方便,例如按列名索引。
当然,如果您只是想用逗号分割文本文件,那么请查看@ Pax的解决方案。
答案 2 :(得分:5)
使用split将线拉开,然后输出您想要的线(比如每隔一列),创建以下xx.pl文件:
while(<STDIN>) {
chomp;
@fields = split (",",$_);
print "$fields[1],$fields[3],$fields[5],$fields[7],$fields[9]\n"
}
然后执行:
$ echo 1,2,3,4,5,6,7,8,9,10 | perl xx.pl
2,4,6,8,10
答案 3 :(得分:3)
如果您在谈论Windows中的CSV文件(例如,从Excel生成),则需要小心处理包含逗号本身但用引号括起来的字段。
在这种情况下,简单的拆分将无效。
答案 4 :(得分:2)
或者,您可以使用标准库中的Text::ParseWords。添加
use Text::ParseWords;
到上面Pax示例的顶部,然后替换
my @fields = parse_line(q{,}, 0, $_);
分裂。
答案 5 :(得分:2)
您可以使用Perl的一些内置运行时选项在命令行上执行此操作:
$ echo "1,2,3,4,5" | perl -a -F, -n -e 'print join(q{,}, $F[0], $F[3]).qq{\n}'
1,4
以上将-a(utosplit)使用逗号的-F(字段)。然后它将加入您感兴趣的字段并将其打印出来(使用行分隔符)。这假设没有嵌套逗号的简单数据。我使用不可打印的字段分隔符(\ x1d)这样做,所以这对我来说不是问题。
有关详细信息,请参阅http://perldoc.perl.org/perlrun.html#Command-Switches。
答案 6 :(得分:1)
看起来没有找到一个很好的符合csv标准的过滤器程序,它只是一个有用的灵活,所以我写了一个。享受。
基本用法是:
bash $ csvfilter [-r&lt; columnTitle&gt;] * [-quote]&lt; csv.file&gt;
#!/usr/bin/perl use strict; use warnings; use Getopt::Long; use Text::CSV; my $always_quote=0; my @remove; if ( ! GetOptions('remove:s'=> \@remove, 'quote-always'=>sub {$always_quote=1;}) ) { die "$0:invalid option (use --remove [--quote-always])"; } my @cols2remove; sub filter(@) { my @fields=@_; my @r; my $i=0; for my $c (@cols2remove) { my $p; #if ( $i $i ) { push(@r, splice(@fields, $i)); } return @r; } # create just one if these my $csvOut=new Text::CSV({always_quote=>$always_quote}); sub printLine(@) { my @fields=@_; my $combined=$csvOut->combine(filter(@fields)); my $str=$csvOut->string(); if ( length($str) ) { print "$str\n"; } } my $csv = Text::CSV->new(); my $od; open($od, "| cat") || die "output:$!"; while () { $csv->parse($_); if ( $. == 1 ) { my $failures=0; my @cols=$csv->fields; for my $rm (@remove) { for (my $c=0; $c$b} @cols2remove); } printLine($csv->fields); } exit(0); \
答案 7 :(得分:0)
除了人们在这里谈到处理逗号分隔文件的内容之外,我还要注意,可以使用数组切片和/或映射提取偶数(或奇数)数组元素:
@myarray[map { $_ * 2 } (0 .. 4)]
希望它有所帮助。
答案 8 :(得分:0)
我个人最喜欢的CSV方式是使用AnyData module。它似乎使事情变得非常简单,并且可以相当容易地删除命名列。 Take a look on CPAN
答案 9 :(得分:-3)
这回答了一个更大的问题,但似乎是一个很好的相关信息。
unix cut命令可以做你想要的(还有更多)。它一直是reimplemented in Perl。