разбирать текстовый файл построчно, затем помещать совпадающую строку в массив и выводить в CSV - PullRequest
0 голосов
/ 16 января 2019

Введите текстовый файл, как показано ниже. Я назвал это $rlseHistRepo.

Route:  TUCSON-AZ
Author: upham
Date:   2018-06-07 20:09:17 UTC
Release:0.0
Content:
        Full Release
Comment:
        Initial setup

*** Modified on Mon Jun 11 19:18:40 PDT 2018 by upham ***
QRC Acceptor: Admin
Log: http://universityofarizona/ECE101/rev0.0_060718_130854-4307-1528769914.qclog
Successful
Status: {Objects succeeded (1)} {}
--------------------------------------------------
Route:  YUMA-AZ
Author: upham
Date:   2018-06-07 20:09:18 UTC
Release:0.0
Content:
        Full Release
Comment:
        Initial setup

*** Modified on Tue Sep 25 15:40:02 PDT 2018 by upham ***
QRC Acceptor: Admin
Log: http://universityofarizona/ECE101/rev0.0_060718_130854-4307-1537915198.qclog
Successful 
Status: {Objects succeeded (33)} {}
--------------------------------------------------

Я хочу написать Perl-скрипт для разбора входного файла выше и вывода в CSV-файл, но у меня возникли проблемы с хэшем и массивом, которые мне не хватает для работы с данными в массиве. Ключ здесь, чтобы получить Вот с чего начинается строка поиска Маршрут: Автор: Дата: Релиз: Журнал: Статус: Содержание: Комментарии: info затем получите строку и запишите в csv файл

Вот мой стартовый скрипт, и я изо всех сил пытаюсь правильно получить массив распечаток csv. Благодарим Вас за помощь, чтобы исправить ее и указать, где и почему массив не получил распечатку должным образом. Заранее большое спасибо

#!/usr/bin/perl

$rlseHistRepo   = $ARGV[0];

my %menu;
open(IN, "< $rlseHistRepo" ) || die "cannot read input file: $!\n";
open(OUTCSV , "> rlseLoggingRepo.csv" ) || die "cannot write output file: $!\n";
print OUTCSV "Site,Author,Release,Date,Version,Changes,Comment\n";
print OUTCSV ",,,,,,,\n";

while(<IN> ) {
    my $line = $_;
    chomp($line);
    if( $line =~ m/^Route:/) {
    my ($item, $rlsSite) = split(/\s+/, $line);
    $menu{$item} = $rlsSite;
    }
    if( $line =~ m/^Author:/) {
    my ($item, $rlsAuthor) = split(/\s+/, $line);
    $menu{$item} = $rlsAuthor;
    }

} 
close(IN);

foreach $item ( keys %menu ) {
    print OUTCSV "$menu{$item},,,,,\n";
    print "$rlsSite{$item},$rlsAuthor{$item},,,,\n";
} 

close(OUTCSV);

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Шаг 1: Добавьте use strict и use warnings. Это выдает ошибки о необъявленных переменных.

Шаг 2: Добавьте my, чтобы объявить $rlseHistRepo. Также добавьте my (%rlsSite, %rlsAuthor), чтобы объявить два хэша, используемых в вашем последнем цикле. Но это странно, так как вы читаете значения из этих хешей без всякого хранения в них данных. Это дает нам несколько ошибок «неинициализированного значения». Поэтому я думаю, что нам нужно переосмыслить вещи.

Идея состоит в том, чтобы создать один хэш для каждой записи. И когда запись заканчивается (когда мы получаем строку из тире), мы выводим эту запись. Примерно так:

my @keys = qw[Route Author Date Release Log
              Status Content Comment];

my %record;

while(<IN> ) {
  chomp;
  if (/-----/) {
    say OUTCSV join ',', @record{@keys};
    %record = ();
  }

  # ignore lines without a ':'
  next unless /:/;
  # ignore the '***' lines
  next if /\*\*\*/;

  my ($key, $value) = split /\s*:\s*/, $_, 2);
  # Some keys have their values on the next line
  if ($value !~ /\S/) {  
    chomp($value = <IN>);
    $value =~ s/^\s+//;
  } 
  $record{$key} = $value;
}

Шаг 3: Очистите вещи, удалив несколько ненужных переменных и превратив их в фильтр Unix (чтение из STDIN и запись в STDOUT) - это на самом деле легче написать и делает вашу программу гораздо более гибкий.

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

my @keys = qw[Route Author Date Release Log
              Status Content Comment];

say "Site,Author,Release,Date,Version,Changes,Comment";
say ",,,,,,,";

my %record;

while (<>) {
  chomp;

  if (/-----/) {
    say join ',', @record{@keys};
    %record = ();
  }

  # ignore lines without a ':'
  next unless /:/;
  # ignore the '***' lines
  next if /\*\*\*/;

  if (my ($key, $value) = split /\s*:\s*/, $_, 2) {
    # Some keys have their values on the next line
    if ($value !~ /\S/) {
      chomp($value = <>);
      $value =~ s/^\s+//;
    }
    $record{$key} = $value;
  }
}

Как уже упоминалось, в производственном коде вы захотите использовать Text :: CSV для получения выходных данных.

0 голосов
/ 16 января 2019

Поскольку вы не указали, как должен выглядеть результат на самом деле, я сделал удар в темноте и сделал предположение, посмотрев на входные данные и ваши регулярные выражения.

Для получения кода качества продукции следуйте советам @Grinnz, чтобы использовать Text :: CSV вместо.

#!/usr/bin/perl
use strict;
use warnings;

print "Entry,Site,Author,Release,Date,Version,Changes,Comment\n";

my @entries;
while(<DATA> ) {
    chomp;
    if (my($site) = /^Route:\s+(.+)$/) {
        # start of new entry
        push(@entries, {
            site => $site,
        });
    } elsif (my($author) = /^Author:\s+(.+)$/) {
        $entries[-1]->{author} = $author;
    }
}

foreach my $index (0..$#entries) {
    my $entry = $entries[$index];
    print "$index,$entry->{site},$entry->{author},,,,,\n";
}

__DATA__
Route:  TUCSON-AZ
Author: upham
Date:   2018-06-07 20:09:17 UTC
Release:0.0
Content:
        Full Release
Comment:
        Initial setup

*** Modified on Mon Jun 11 19:18:40 PDT 2018 by upham ***
QRC Acceptor: Admin
Log: http://universityofarizona/ECE101/rev0.0_060718_130854-4307-1528769914.qclog
Successful
Status: {Objects succeeded (1)} {}
--------------------------------------------------
Route:  YUMA-AZ
Author: upham
Date:   2018-06-07 20:09:18 UTC
Release:0.0
Content:
        Full Release
Comment:
        Initial setup

*** Modified on Tue Sep 25 15:40:02 PDT 2018 by upham ***
QRC Acceptor: Admin
Log: http://universityofarizona/ECE101/rev0.0_060718_130854-4307-1537915198.qclog
Successful 
Status: {Objects succeeded (33)} {}
--------------------------------------------------

Пример выполнения:

$ perl dummy.pl
Entry,Site,Author,Release,Date,Version,Changes,Comment
0,TUCSON-AZ,upham,,,,,
1,YUMA-AZ,upham,,,,,

РЕДАКТИРОВАТЬ: альтернативный подход будет использовать

if (/^Route:/../^----------/) {
    # we are inside a log entry...
}

, а затем обнаружить

  • строк ключевых слов с my($keyword, $data) = /^(\w+):\s*(.*)$/;
  • текстовые строки с my($line) = /^\s+(.+)$/;

внутри этого блока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...