基于输入文件的 PERL 固定宽度到 CSV

PERL Fixed Width to CSV based on Input Files

已编辑:我正在尝试创建一个简短的脚本,该脚本需要一个输入固定宽度文件和一个具有每个属性的起始位置和长度的文件,然后将文件输出为 CSV 而不是固定宽度。我还没有搞砸删除空格,目前正专注于构建文件 reader 部分。

修正: 我当前的问题是此代码 returns 来自第三行的 $StartPosition 数据和来自第四行的 $Length 数据,当它们都应该首先在 COMMA 的第一行中找到时。我不知道是什么促使了这种行为。

下一期:它只读取 practice_data.txt 中的第一条记录我猜这是我需要告诉 COMMA 回到开头的地方?

while (my $sourceLine = <SOURCE>) {
   $StartPosition = 0;
   $Length = 0;
   $Output = "";
   $NextRecord ="";
   while (my $commaLine = <COMMA>) {
       my $Comma = index($commaLine, ',');
       print "Comma location found at $Comma \n";
       $StartPosition = substr($commaLine, 0, $Comma);
       print "Start position is $StartPosition \n";
       $Comma = $Comma + 1
       $Length = substr($commaLine, $Comma);
       print "Length is $Length \n";
       $NextRecord = substr($sourceLine, $StartPosition, $Length);
       $Output = "$Output . ',' . $NextRecord";
       }
   print OUTPUT "$Output \n";
}

practice_data.txt

1234512345John      Doe       123 Mulberry Lane   Columbus  Ohio      43215Johnny         Jane      
5432154321Jason     McKinny   423 Thursday Lane   Columbus  Ohio      43212Jase           Jamie     
4321543212Mike      Jameson   289 Front Street    Cleveland Ohio      43623James          Sarah      

每条记录的长度为 100 个字符。 Definitions.txt:

0,10
10,10
20,10
30,20
50,10
60,10
70,5
75,15
90,10

您似乎对如何读取 COMMA 文件句柄的内容有些困惑。每次您读取 <COMMA> 时,您都在从该文件中读取另一行。相反,将一行读入像 my $line = <FH> 这样的标量并改用它:

while (my $source_line = <SOURCE>) {
    $StartPosition = 0;
    $Length = 0;
    $Output = "";
    $Input = $_;
    $NextRecord ="";
    while (my $comma_line = <COMMA>) {
        my $Comma = index($comma_line, ',');
        print "Comma location found at $Comma \n";
        $StartPosition = substr($comma_line, 0, $Comma);
        print "Start position is $StartPosition \n";
        $Length = substr($comma_line, $Comma);
        print "Length is $Length \n";
        $NextRecord = substr($Input, $StartPosition, $Length) + ',';
        $Output = "$Output$NextRecord";
    }

    print OUTPUT "$Output \n";
}

提供足够的信息总是有帮助的,这样我们至少可以进行一些测试,而不必阅读您的代码并想象数据的样子。

我建议您先使用包含字段规范的文件构建模板后使用 unpack。请注意,A 字段说明符会删除数据中的尾随空格。

使用 Text::CSV 模块解析或生成格式正确的 CSV 数据几乎是必不可少的。而且我使用了 autodie pragma 以避免必须显式检查和报告每个 I/O 操作的状态。

我用过这个数据

my_source_data.txt

12345678  ABCDE1234FGHIJK

my_field_spec.txt

0,8
10,5
15,4
19,6

还有这个节目

use strict;
use warnings;
use 5.010;
use autodie;

use Text::CSV;

my @template;
open my $field_fh, '<', 'my_field_spec.txt';
while ( <$field_fh> ) {
  my (@info) = /\d+/g;
  die unless @info == 2;
  push @template, sprintf '@%dA%d', @info;
}

my $template = "@template";

open my $source_fh, '<', 'my_source_data.txt';

my $csv = Text::CSV->new( { binary => 1, eol => $/ } );

while ( <$source_fh> ) {
  my @fields = unpack $template;
  $csv->print(\*STDOUT, \@fields);
}

输出

12345678,ABCDE,1234,FGHIJK