【问题标题】:Parse fixed-width files解析固定宽度的文件
【发布时间】:2011-06-22 02:45:32
【问题描述】:

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

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

其余文件采用类似的格式,&lt;c&gt; 将标记列的开头,但它们具有各种(未知)列和空间宽度。解析这些文件的最佳方法是什么?

我尝试使用Text::CSV,但由于没有分隔符,因此很难获得一致的结果(除非我使用的模块错误):

my $csv = Text::CSV->new();
$csv->sep_char (' ');

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

【问题讨论】:

  • 你为什么反对“解析”标签?这是一个解析问题。您需要 Perl 中的解决方案并不意味着它不是解析问题。
  • 因为我不想要一个通用的解决方案
  • 也许我误解了...我认为将“解析”放在那里会带来一大堆与我的情况无关的解决方案(即 python、php 等)...谢谢
  • 我猜 CPAN 上有一个(或两个或三个或...)模块用于此目的?至于动态宽度,只需在读取标题后动态构建适当的“模板” - 或者 宽度是否取决于绝对疯狂的东西,例如每列数据的最大宽度?
  • @pst - 查看我的答案。 CPAN 有一个模块,不仅可以解析,而且可以自动为您确定宽度(启发式):)

标签: perl parsing


【解决方案1】:

正如 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 = [ [ “戴夫”, “托马斯”, '123 主要' ], [ '担', “安德森”, '456 中心' ], [ '威尔玛', '彩虹', '789 街' ] ];

【讨论】:

    【解决方案2】:

    CPAN 来救援!

    DataExtract::FixedWidth 不仅解析固定宽度的文件,而且(基于 POD)似乎足够聪明,可以自己从标题行中找出列宽!

    【讨论】:

    • 顺便说一句,作者偶尔会在这里闲逛。
    • DVK++ =) 谢谢! DE:FW 也通过tons of test input. 进行了很好的测试
    【解决方案3】:

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

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

    在解压模板里面,“A###”,你可以放每个A的字段宽度。 您可以使用多种其他格式进行混合和匹配,即整数字段等... 如果文件是固定宽度的,比如大型机文件,那么这应该是最简单的。

    【讨论】:

    • 这是我的问题的一部分......字段的宽度将根据我提供的文件而改变。有没有办法解包从标题中检测宽度?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 2023-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多