Как разобрать несколько файлов в Perl - PullRequest
0 голосов
/ 17 марта 2020

У меня есть этот пример данных, которые я хотел проанализировать, и существует более 10 таких файлов, как я могу их проанализировать? Мне нужна вторая строка данных и извлекаю только код, дату и сообщение.

enter image description here

foreach my $dir (@not_proc_dir) {
    chomp ($dir);
    print "$dir\n";

    opendir (DIR, $dir) or die "Couldn't open directory, $!";
    while ( my $file = readdir DIR) {
            next if $file =~ /^\.\.?$/;
    #       next if (-d $file);
            next if -d "$dir/$file";
            #print "\t$file\n";
            $file = "${dir}/${file}";
            if ($file =~ /\.err/) {
                    parse_err($file);
            }
            elsif ($file =~ /\.xml$/) {
                    parse_xml($file);
            }
            elsif ($file =~ /\.enrich/){
                    parse_enrich($file);
            }
    }
    close DIR;

sub parse_err {
         my $xml = shift;
        my @array = open(DATA, $xml) or die "Couldn't open file $xml, $!";
        my $secLine;
        foreach(@array) {
                my $secLine = $_;
                last;
        }
        close DATA;
}

Ответы [ 3 ]

3 голосов
/ 17 марта 2020

open не возвращает строки файла. Вам нужно использовать readline .

open my $in, '<', $xml or die "Can't open $xml: $!";
<$in>;  # Ignore the first line.
my $second_line = <$in>;

Оператор с бриллиантами <$in> - это более короткая версия readline $in.

2 голосов
/ 17 марта 2020

Эта подпрограмма очень странная.

sub parse_err {
    my $xml = shift;
    my @array = open(DATA, $xml) or die "Couldn't open file $xml, $!";
    my $secLine;
    foreach (@array) {
        my $secLine = $_;
        last;
    }
    close DATA;
}

open() просто возвращает значение true или false, указывающее, был ли файл успешно открыт. Хранение этого возвращаемого значения в массиве не имеет смысла.

Затем вы объявляете переменную с именем $secLine, которую вы никогда не используете.

Затем вы выполняете итерацию по содержимому @array (которое только содержит один элемент, поэтому l oop выполняется только один раз).

В теле l oop вы объявляете другую переменную с именем $secLine и копируете значение из массива в эту переменную. Затем вы выходите из l oop - поэтому ваша вторая переменная с именем $secLine выходит из области видимости и перестает существовать. Это фактически означает, что ваш l oop не имеет никакого эффекта.

В общем, вы, кажется, очень смущены. Если это курсовая работа, то я рекомендую вам go просмотреть ваши заметки в классе и поближе познакомиться с разделом о чтении данных из файлов.

Я думаю, вы хотите что-то вроде этого:

sub parse_err {
  my ($filename) = @_;

  open my $fh, '<', $filename or die "Could'nt open file '$filename': $!\n";

  <$fh>; # Read and ignore first line.
  my $line = <$fh>; # Read second line

  my (undef, $code, undef, $date, $time, $message) = split /\s+/, $line, 6;

  $date = "$date $time";

  return ($code, $date, $message);
}

Эта подпрограмма возвращает три значения - $code, $date и $message. Вам нужно будет присвоить их переменным при вызове подпрограммы, а затем сделать с ними что-то полезное.

my ($code, $date, $message) = parse_err($file);
1 голос
/ 17 марта 2020

Attn: OP

В функции, пожалуйста, предоставьте образец входных данных в текстовом формате (копирование + вставка с терминала windows).

Код очень просто реализовать с помощью perl script

определить интересующее регулярное выражение

искать файлы * .err

  • открыть файл

  • поиск шаблона

  • извлечение данных

  • распечатка найденных данных

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

my $re = qr/\d\s+(\d{4})\s+E\s+(\d{1,2}-\d{1,2}-\d{4})\s+(\d{1,2}:\d{1,2}:\d{1,2})\s+(.*)/;

for my $filename ( glob("*.err") ) {
    say '------------------';
    say $filename;
    say '------------------';
    open my $fh, '<', $filename
        or die "Couldn't open $filename : $!";

    while( <$fh> ) {
        chomp;
        next unless /$re/;
        my($code,$date,$time,$msg) = ($1,$2,$3,$4);
        say 'Code: '    . $code;
        say 'Date: '    . $date;
        say 'Time: '    . $time;
        say 'Message: ' . $msg;
        say '------------------';
    }

    close $fh;
}

Входные данные

4   0
1   9001    E   10-17-2019  23:15:39    ORA-01400: cannot insert NULL into
Error at character 139 of the following SQL;
insert into lot (lot_key, lot_id, part_cnt,
.....
1   9001    E   10-17-2019  23:15:39    Error Executing lot_put_row 2
1   9001    E   10-17-2019  23:15:39    DBASCII: Exit called from file ora/dbreader.pc at line 10666
Version 2.6.2 - April 26, 2017 (DB schema 10.6rl)
1   9001    E   10-17-2019  23:15:39
ROLLBACK was successfill

Выход

------------------
ora-err-01400.err
------------------
Code: 9001
Date: 10-17-2019
Time: 23:15:39
Message: ORA-01400: cannot insert NULL into
------------------
Code: 9001
Date: 10-17-2019
Time: 23:15:39
Message: Error Executing lot_put_row 2
------------------
Code: 9001
Date: 10-17-2019
Time: 23:15:39
Message: DBASCII: Exit called from file ora/dbreader.pc at line 10666
------------------
...