Невозможно получить несколько значений столбца из файла в Perl - PullRequest
0 голосов
/ 27 января 2020

У меня есть файл со следующим содержимым:

TIME                                                                                                                                                         

DATE     TIME         DAY                                                                                                                     
191227   055526       FRI                                                                                                                        

RC      DEV    SERVER                                                                                                                                        
RC1            SERVER1                                                                                                                         
RC2            SERVER2                                                                                                                                
RC3            SERVER3                                                                                                                                

END                                                                                                                                                                                                                                                                                    

Я получаю значения аргументов из этого файла, скажем, если я передам DATE в качестве аргумента скрипту, я получаю соответствующее значение DATE. то есть, 191227

Когда я передаю несколько аргументов, скажите DATE, DAY, я должен получить значения:

DATE=191227
DAY=FRI

Но я получаю вот что:

DATE=191227
DAY=NULL

И если я передам RC в качестве аргумента, я должен получить: RC=RC1,RC2,RC3

Сценарий выглядит следующим образом:

#!/usr/bin/perl

use strict;
use Data::Dumper;
print Dumper(\@ARGV);

foreach my $name(@ARGV){
    print "NAME:$name\n";
    my ($result, $start, $stop, $width) = "";
    while(my $head = <STDIN>)
    {
        if( $head =~ (m/\b$name\b/g))
        {
                $start = (pos $head) - length($name); 
                $stop = (pos $head);
                my $line = <STDIN>;

                pos $head = $stop+1;
                $head =~ (m/\b/g);
                $width = (pos $head) - $start;
                $result = substr($line,$start,$width);
        }
    }
    $result =~ s/^\s*(.*?)\s*$/$1/;

    print "$name=";
    $result = "NULL" if ( $result eq "" );
    print "$result\n";  
}

Может кто-нибудь помочь мне получить значения если я передам несколько аргументов также, если предположим, что значение аргумента содержит данные в несколько строк, то должны быть напечатаны значения, разделенные запятыми (например: для RC, RC=RC1,RC2,RC3).

1 Ответ

1 голос
/ 27 января 2020

Вот пример, предполагая, что входной файл имеет имя file.txt, а значения начинаются с той же горизонтальной позиции, что и клавиши:

package Main;
use feature qw(say);
use strict;
use warnings;

use Data::Dumper qw(Dumper);

my $self = Main->new(fn => 'file.txt', params => [@ARGV]);
$self->read_file();
$self->print_values();

sub read_file {
    my ( $self ) = @_;

    my $fn = $self->{fn};
    open ( my $fh, '<', $fn ) or die "Could not open file '$fn': $!";
    local $/ = "";  #Paragraph mode
    my @blocks = <$fh>;
    close $fh;
    $self->{values} = {};
    for my $block (@blocks) {
        $self->parse_block( $block );
    }
}

sub parse_block {
    my ( $self,  $block ) = @_;

    my @lines = split /\n/, $block;
    my $header = shift @lines;
    my ($keys, $startpos) = $self->get_block_keys( $header );

    for my $line ( @lines ) {
        for my $key (@$keys) {
            my $startpos = $startpos->{$key};
            my $str = substr $line, $startpos;
            my ( $value ) = $str =~ /^(\S+)/;
            if ( defined $value ) {
                push @{$self->{values}{$key}}, $value;
            }
        }
    }
}

sub get_block_keys {
    my ( $self,  $header ) = @_;

    my $values = $self->{values};
    my @keys;
    my %spos;
    while ($header =~ /(\S+)/g) {
        my $key = $1;
        my $startpos =  $-[1];
        $spos{$key} = $startpos;
        push @keys, $key;
    }
    for my $key (@keys) {
        if ( !(exists $values->{$key}) ) {
            $values->{$key} = [];
        }
    }
    return (\@keys, \%spos);
}

sub new {
    my ( $class, %args ) = @_;

    return bless \%args, $class;
}

sub print_values {
    my ( $self ) = @_;

    my $values = $self->{values};
    for my $key (@{$self->{params}}) {
        my $value = "<NO VALUE FOUND>";
        if ( exists $values->{$key} ) {
            $value = join ",", @{$values->{$key}};
        }
        say "$key=$value";
    }
}

Редактировать

Если вы хотите чтобы вместо этого прочитать файл из STDIN, измените следующую часть кода:

# [...]
my $self = Main->new(params => [@ARGV]);
$self->read_file();
$self->print_values();

sub read_file {
    my ( $self ) = @_;

    local $/ = "";  #Paragraph mode
    my @blocks = <STDIN>;
    $self->{values} = {};
    for my $block (@blocks) {
        $self->parse_block( $block );
    }
}
# [...]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...