【发布时间】:2013-05-17 19:43:52
【问题描述】:
出于工作目的,我有几个 CSV 文件已被供应商升级修改,现在它们包含的列比以前多 80 列。不利的一面是,这些文件用于计费,因此我们需要修剪掉新列。好处是所有列都已添加到记录的末尾。较旧的记录包含 251 列。新记录包含 336 个。
所以,我正在编写的脚本将接受 CSV 文件名作为参数,在原地编辑它,因为文件可能非常大,删除前两行和最后一行,最后删除新列(不仅仅是清空它们的内容,完全删除它们,所以如果原始格式有N列,处理后的新格式应该只有N列)
这是我目前所拥有的:
use strict;
use warnings;
#Use Tie::File to modify file contents directly on disk, without reading
#to memory.
use Tie::File;
#Use Text::CSV_XS to quickly remove columns from CSV. External library
#used to compensate for quoted fields.
use Text::CSV_XS;
my $csvparser = Text::CSV_XS->new () or die "".Text::CSV_XS->error_diag();
my $file;
foreach $file (@ARGV){
my @CSVFILE;
my $csvparser = Text::CSV_XS->new () or die "".Text::CSV_XS->error_diag();
tie @CSVFILE, 'Tie::File', $file or die $!;
shift @CSVFILE;
shift @CSVFILE;
pop @CSVFILE;
for my $line (@CSVFILE) {
$csvparser->parse($line);
my @fields = $csvparser->fields;
splice @fields, -85;
$line = $csvparser->combine(@fields);
}
untie @CSVFILE;
}
这将运行,并且第一部分运行正确(删除前 2 行和最后一行)。但是我不确定如何继续删除新列。我一直在阅读 Text::CSV_XS 的文档,但似乎找不到任何可以删除列的函数。一些例子可能会有所帮助,但我承认我的 perl 技能不是很好。我想要使用该模块的主要原因是这些 CSV 文件有时确实包含带逗号的字段,用引号括起来,模块可以处理。
任何关于如何解决这个问题的建议都会很棒。另外,如果我的方法有问题,请告诉我。我绝不是 perl 专家,并且愿意接受任何有用的批评,因为这将被输入计费系统。
编辑:将下面的建议包含在代码中。如下所述,运行此程序时,源文件的内容会在每一行替换为单个“1”。
【问题讨论】:
-
请不要对 Perl 局部变量使用大写字母。它们是为
@ARGV和Text::CSV_XS等全局名称保留的。 -
我的印象是基于旧骆驼书的标准是文件句柄使用全部大写? docstore.mik.ua/orelly/perl/perlnut/ch04_09.htm那个风格变了吗??
-
旧式文件句柄也是 global 的,所以全大写。当前的最佳实践是对文件句柄使用词法标量变量,因此现在是
open my $fh, '<', 'filename'而不是open FH, 'filename'