无法在Perl中以特定格式打印某些数组元素

时间:2016-09-10 09:24:53

标签: regex perl

使用以下脚本处理文件并以特定格式提供输出。 我无法制作所需的输出表。

输入

#!/usr/bin/perl -w

use strict;
use warnings;
use Data::Dumper;
use diagnostics;

my $temp_M1SLP;
my @temp_M1SLP;

my $start_run = time();

my $header = "CODE           NAME         DST    TY  DAIS             NO    STAT             TM     TMW";
print "$header\n";

open( INFILE, "<Sample1.log" ) or die "Couldn't open file M1SLP.txt\n";
while ( my $line = <INFILE> ) {

    chomp($line);
    @temp_M1SLP = $line;

    if ( $line =~ /^\d-\d+/ ) {
        $temp_M1SLP[0] = ( substr $line, 0,  14 );
        $temp_M1SLP[1] = ( substr $line, 15, 7 );
        $temp_M1SLP[2] = ( substr $line, 28, 5 );
        $temp_M1SLP[3] = ( substr $line, 35, 4 );

        printf( "%-10s", $temp_M1SLP[0] );
        printf( "%-10s", $temp_M1SLP[1] );
        printf( "%-8s",  $temp_M1SLP[2] );
        printf( "%-5s",  $temp_M1SLP[3] );
    }

    next if ( $line =~ /^               DAIS             NO    STAT             TM     TMW/ );

    {
        while ( $line =~ /^\s+\w+/ ) {

            $temp_M1SLP[4] = ( substr $line, 15, 15 );
            $temp_M1SLP[5] = ( substr $line, 32, 4 );
            $temp_M1SLP[6] = ( substr $line, 38, 14 );
            $temp_M1SLP[7] = ( substr $line, 55, 7 );
            $temp_M1SLP[8] = ( substr $line, 62, 5 );

            printf( "%-18s", $temp_M1SLP[4] );
            printf( "%-6s",  $temp_M1SLP[5] );
            printf( "%-8s",  $temp_M1SLP[6] );
            printf( "%-8s",  $temp_M1SLP[7] );
            printf( "%-5s",  "$temp_M1SLP[8]\n" );

            $line = <INFILE>;
        }
    }
}

my $end_run = time();

输出文件将采用此格式

CODE           NAME         DST     TY   DAIS                NO    STAT             TM     TMW
2-2017        121CM02       AVA     PP   EP022CM02           1     DM-ACT-AVA              10
2-2017        121CM02       AVA     PP   EP032CM02           1     DM-BAT-BTA       20        
2-2033        119LHR        AVA     PP   HLR3EP03203         1     DM-BAT-BTA            
2-2110        119A1AU       AVA     PP   A1AUEP080           1     DM-BAT-BTA            
2-2110        119A1AU       AVA     PP    A1AUEP090          1     DM-BAT-BTA            
2-2110        119A1AU       AVA     PP   A1AUEP110           1     DM-BAT-BTA            
2-2110        119A1AU       AVA     PP   A1AUEP100           1     DM-BAT-BTA            

输入文件(Sampel1.txt)如图所示

CODE           NAME         DST    TY
2-2017         121CM02      AVA    PP

               DAIS             NO    STAT             TM     TMW
               EP022CM02           1  DM-ACT-AVA              10
               EP032CM02           1  DM-BAT-BTA       20       

2-2033         119LHR       AVA    PP

               DAIS             NO    STAT             TM     TMW
               HLR3EP03203         1  DM-BAT-BTA              

2-2110         119A1AU      AVA    PP

               DAIS             NO    STAT             TM     TMW
               A1AUEP080           1  DM-BAT-BTA              
               A1AUEP090           1  DM-BAT-BTA              
               A1AUEP110           1  DM-BAT-BTA              
               A1AUEP100           1  DM-BAT-BTA              

但是目前,我的输出结果如下。请支持检查代码并更正

CODE           NAME         DST    TY  DAIS              NO    STAT               TM     TMW
2-2017        121CM02   AVA     PP   EP022CM02            1  DM-ACT-AVA            10
  EP032CM02            1  DM-BAT-BTA    20        

 2-2033        119LHR    AVA     PP   HLR3EP03203          1  DM-BAT-BTA            
 2-2110        119A1AU   AVA     PP   A1AUEP080            1  DM-BAT-BTA            
    A1AUEP090            1  DM-BAT-BTA            

   A1AUEP110            1  DM-BAT-BTA            

   A1AUEP100            1  DM-BAT-BTA

2 个答案:

答案 0 :(得分:2)

我本来希望看到更多的努力来解决这个问题,特别是我不明白为什么在要求你这样做之后我必须为你格式化你的Perl代码

但是,这是一个解决方案,可以解决这个问题

#!/usr/bin/perl

use strict;
use warnings 'all';

my $header = "CODE           NAME         DST    TY  DAIS             NO    STAT             TM     TMW";

# Construct the printf format string to reproduce the header line spacing
#
my $format = do {

    my @start;
    push @start, $-[0] while $header =~ /\S+/g;

    my @sizes = map { $start[$_+1] - $start[$_] } 0 .. $#start-1;

    join("", map { "%-${_}s" } @sizes, "") . "\n";
};

printf $format, split ' ', $header;

open my $fh, '<', 'Sample1.log' or die qq{Couldn't open file "Sample1.log" for input: $!};

my @head;

while ( <$fh> ) {

    # Example:
    # CODE           NAME         DST    TY
    # 2-2017         121CM02      AVA    PP

    if (/^\d+-\d+/) {
        @head = unpack 'A15 A13 A7 A*';
    }

    # Example:
    #                DAIS             NO    STAT             TM     TMW
    #                EP022CM02           1  DM-ACT-AVA              10
    #                EP032CM02           1  DM-BAT-BTA       20       

    elsif ( /\d/ ) {

        my @tail = unpack '@15 A17 A6 A17 A7 A*';
        $tail[1] += 0;

        printf $format, @head, @tail;
    }
}

输出

CODE           NAME         DST    TY  DAIS             NO    STAT             TM     TMW
2-2017         121CM02      AVA    PP  EP022CM02        1     DM-ACT-AVA              10
2-2017         121CM02      AVA    PP  EP032CM02        1     DM-BAT-BTA       20     
2-2033         119LHR       AVA    PP  HLR3EP03203      1     DM-BAT-BTA              
2-2110         119A1AU      AVA    PP  A1AUEP080        1     DM-BAT-BTA              
2-2110         119A1AU      AVA    PP  A1AUEP090        1     DM-BAT-BTA              
2-2110         119A1AU      AVA    PP  A1AUEP110        1     DM-BAT-BTA              
2-2110         119A1AU      AVA    PP  A1AUEP100        1     DM-BAT-BTA              

答案 1 :(得分:0)

我的解决方案首先跳过所有不相关的行。当找到以\d-\d+开头的行(如2-2017…)时,字段CODE,NAME,DST和TY仅在全局变量中存储。我将数组@temp_M1SLP替换为显式变量名。

如果找到的行看起来像DAIS,NO,...(由空白后的单词标识的行),那么上一节中的值(CODE,NAME,...)打印当前值。

我的代码或多或少是代码的混乱版本。但是,我更喜欢Borodin's solution,因为它更优雅。

#!/usr/bin/env perl

use strict;
use warnings 'all';

my $header = "CODE          NAME      DST     TY   DAIS                NO  STAT          TM     TMW";
print "$header\n";

my ( $code, $name, $dst, $ty );
open( INFILE, "<Sample1.log" ) or die "Couldn't open file Sample1.log\n";
while ( my $line = <INFILE> ) {

    chomp($line);

    # skip header, subheader, and empty lines:
    next if ( $line =~ /^CODE\s+NAME\s+DST\s+TY/ );
    next if ( $line =~ /^\s+DAIS\s+NO\s+STAT\s+TM\s+TMW/ );
    next if ( $line !~ /\S/ );

    # code section found? then remember the values
    # but don't print them yet.
    if ( $line =~ /^\d-\d+/ ) {
        $code = substr( $line, 0,  14 );
        $name = substr( $line, 15, 7 );
        $dst  = substr( $line, 28, 5 );
        $ty   = substr( $line, 35, 4 );
    }

    # line with DAIS, NO, ... found? then print the columns from
    # the code section _and_ the columns of this line:
    if ( $line =~ /^\s+\w+/ ) {
        my $dais = substr( $line, 15, 15 );
        my $no   = substr( $line, 32, 4 );
        my $stat = substr( $line, 38, 14 );
        my $tm   = substr( $line, 55, 7 );
        my $tmw  = substr( $line, 62, 5 );

        printf( "%-10s",  $code );    # from code section
        printf( "%-10s",  $name );    #        "
        printf( "%-8s",   $dst );     #        "
        printf( "%-5s",   $ty );      #        "
        printf( "%-18s",  $dais );    # from current line
        printf( "%-6s",   $no );      #        "
        printf( "%-8s",   $stat );    #        "
        printf( "%-8s",   $tm );      #        "
        printf( "%-5s\n", $tmw );     #        "
    }

}

输出

CODE          NAME      DST     TY   DAIS                NO  STAT          TM     TMW
2-2017        121CM02   AVA     PP   EP022CM02            1  DM-ACT-AVA            10   
2-2017        121CM02   AVA     PP   EP032CM02            1  DM-BAT-BTA    20           
2-2033        119LHR    AVA     PP   HLR3EP03203          1  DM-BAT-BTA                 
2-2110        119A1AU   AVA     PP   A1AUEP080            1  DM-BAT-BTA                 
2-2110        119A1AU   AVA     PP   A1AUEP090            1  DM-BAT-BTA                 
2-2110        119A1AU   AVA     PP   A1AUEP110            1  DM-BAT-BTA                 
2-2110        119A1AU   AVA     PP   A1AUEP100            1  DM-BAT-BTA