3

出于工作目的,我有几个 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”。

4

1 回答 1

4

是的,你可以按照你的要求去做,虽然我不希望有任何很快的速度。

像这样的东西应该工作

use strict;
use warnings;

use Tie::File;
use Text::CSV_XS;

my $csv = Text::CSV_XS->new or die Text::CSV_XS->error_diag;

foreach my $file (@ARGV) {

    tie my @lines, 'Tie::File', $file or die $!;

    splice @lines, 0, 2;
    pop @lines;

    for my $line (@lines) {
        $csv->parse($line);
        my @fields = $csv->fields;
        splice @fields, -80;
        $csv->combine(@fields);
        $line = $csv->string;
    }

    untie @lines;
}
于 2013-05-22T16:57:33.077 回答