解析固定宽度文件

9

我有很多固定宽度字段的文本文件:

<c>     <c>       <c>
Dave    Thomas    123 Main
Dan     Anderson  456 Center
Wilma   Rainbow   789 Street

其余文件的格式类似,其中<c>将标记列的开头,但它们具有各种(未知)列和空格宽度。最好的解析这些文件的方法是什么?
我尝试使用Text::CSV,但由于没有分隔符,很难获得一致的结果(除非我使用模块错误)。
my $csv = Text::CSV->new();
$csv->sep_char (' ');

while (<FILE>){
    if ($csv->parse($_)) {
        my @columns=$csv->fields();
        print $columns[1] . "\n";
    }
}

1
你为什么反对“解析”标签?这是一个解析问题。你需要用Perl解决它并不意味着它不是一个解析问题。 - zwol
因为我不想要一个通用的解决方案。 - user_78361084
也许我误解了...我认为在那里加入“解析”会带来许多与我的情况无关的解决方案(例如Python、PHP等)...谢谢 - user_78361084
我猜在CPAN上有一个(或两个或三个或更多)模块可以做到这一点?至于动态宽度,只需在读取标题后动态构建相应的“模板”即可 - 或者宽度是否取决于像每列数据的最大宽度这样绝对疯狂的东西? - user166390
@pst - 请看我的回答。CPAN有一个模块不仅可以解析,还可以为您自动确定宽度(启发式地):) - DVK
DataExtract::Fixed width就是这样做的。 - Evan Carroll
3个回答

12

正如user604939所提到的,unpack是处理定长字段的工具。然而,unpack需要传递一个模板来配合使用。由于您说您的字段可能会改变宽度,因此解决方案是从文件的第一行构建此模板:

my @template = map {'A'.length}        # convert each to 'A##'
               <DATA> =~ /(\S+\s*)/g;  # split first line into segments
$template[-1] = 'A*';                  # set the last segment to be slurpy

my $template = "@template";
print "template: $template\n";

my @data;
while (<DATA>) {
    push @data, [unpack $template, $_]
}

use Data::Dumper;

print Dumper \@data;

__DATA__
<c>     <c>       <c>
Dave    Thomas    123 Main
Dan     Anderson  456 Center
Wilma   Rainbow   789 Street

输出如下内容:

模板:A8 A10 A*
$VAR1 = [
          [
            'Dave',
            'Thomas',
            '123 Main'
          ],
          [
            'Dan',
            'Anderson',
            '456 Center'
          ],
          [
            'Wilma',
            'Rainbow',
            '789 Street'
          ]
        ];

6

CPAN来帮忙了!

DataExtract::FixedWidth 不仅可以解析定长文件,而且(根据POD)似乎足够聪明,能够自行从标题行中确定列宽度!


顺便说一句,作者偶尔会在 Stack Overflow 上闲逛。 - DVK
DVK++ =) 谢谢!DE:FW 也经过了大量测试,有大量的测试输入。 - Evan Carroll

3

只需使用Perl的unpack函数。类似这样:

while (<FILE>) {
    my ($first,$last,$street) = unpack("A9A25A50",$_);

    <Do something ....>
}

在解包模板“A###”中,您可以为每个A字段设置宽度。还有许多其他格式可供组合使用,例如整数字段等等...如果文件是固定宽度的,例如主机文件,则应该最容易处理。

这是我的问题的一部分...字段的宽度将根据我提供的文件而改变。是否有一种方法让unpack从头部检测宽度? - user_78361084

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接