Найдите строку и сохраните искомую строку в массиве, используя perl - PullRequest
2 голосов
/ 29 марта 2020

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

Вот код, который я пробовал

use warnings;
use Data::Dumper;

my $start_run = time();

    while (<DATA>){
        my $line=$_  ;
        if ($line =~ m/Date/) {
           my @result = grep (/Date/, $line);
           print @result;
       }
     }


#####
my $end_run = time();
my $run_time = sprintf "%.2f", (($end_run - $start_run) / 60);
print "Elapsed: $run_time minutes\n";


__DATA__
ServerName: (DESCRIPTION=(CONNECT_TIMEOUT=60)(RETRY_COUNT=5)(ADDRESS=(PROTOCOL=TCP)(HOST=xbian.dbaas.ing.net)(PORT=121))(CONNECT_DATA=(SERVER=DEDI)(SERVICE_NAME=pmx0))) ServerType: Oracle DatabaseName: MX_FN_OWNER RDBMSAccess: NATIVE_OCI ConnectionName: Mx0_MUXFO_1_1 ConnectionNo: 1  Date: 2020-03-29 08:58:10
insert into MX_FN_OWNER.TRN_EDBF (TIMESTAMP,M_IDENTITY,M_REFERENCE,M_USER,M_GROUP,M_DESK,M_DATE_SYS,M_DATE_CMP,M_TIME_CMP,M_SDATE_CMP,M_STIME_CMP,M_COMMENT,M_ERROR,M_START_END,M_TIME_CPU,M_TIME_SYB,M_TIME_ELAP,M_SCRPT_NAME,M_UNIT_NAME,M_ERR_COUNT,M_NPID) values (0,TRN_EODA_DBFS.nextval,:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18,:19) (Bulk_Copy begin, 19 columns, 1 Flush size)

                              ==============================================
ServerName: (DESCRIPTION=(CONNECT_TIMEOUT=60)(RETRY_COUNT=5)(ADDRESS=(PROTOCOL=TCP)(HOST=xb305-scan.net)(PORT=121))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=pmx02fn))) ServerType: Oracle DatabaseName: MX_FN_OWNER RDBMSAccess: NATIVE_OCI ConnectionName: Mx0_MXFO_168991_1 ConnectionNo: 1  Date: 2020-03-29 09:21:10
Mux execution time: 00:00:00   3 ms 

Видимо, в каждой строке есть Дата, и меня просто интересуют Дата и время у него есть sp, что я могу вычесть время между двумя строками и сохранить его. Но когда я пытаюсь grep, вывод - целая строка. я не могу разбить строку, так как нет разделителя.

Есть ли способ, которым я могу просто получить дату: 2020-03-29 09:21:10, связанную с каждой строкой

Сценарий преобразования

#!/usr/bin/perl

use strict;
use warnings;

use DateTime::Format::Strptime;

my $parser = DateTime::Format::Strptime->new(
  pattern => 'd{4}-\d{2}-\d{2}\h+\d{2}:\d{2}:\d{2}',
  on_error => 'croak',
);

my $dt = $parser->parse_datetime('2020-03-29 08:58:10');

print "$dt\n";

Спасибо

Ответы [ 3 ]

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

Вы можете сопоставить дату как образец и использовать \K для сброса буфера соответствия.

Обратите внимание, что образец не проверяет само время даты.

Затем добавьте все совпадение использование $& для массива.

\bDate:\h+\K\d{4}-\d{2}-\d{2}\h+\d{2}:\d{2}:\d{2}$

Пояснение

  • \bDate:\h+\K Совпадение Date: и 1+ горизонтальных пробельных символов.
  • \K Сбросить буфер совпадений
  • \d{4}-\d{2}-\d{2}\h+\d{2}:\d{2}:\d{2} Соответствовать дате и времени, как шаблон
  • $ Если значение всегда в конце, вы можете утверждать конец строки

Regex demo | Perl демо

Например:

my @arr;
while (<DATA>){
    my $line=$_  ;
    if ($line =~ m/\bDate:\h+\K\d{4}-\d{2}-\d{2}\h+\d{2}:\d{2}:\d{2}$/) {
        push(@arr, $&);
    }
}

for my $i (0 .. $#arr) {
    if (exists($arr[$i + 1])) {
        my $currentDateTime = Time::Piece->strptime(
            $arr[$i],
            "%Y-%m-%d %H:%M:%S");
        my $nextDateTime = Time::Piece->strptime(
            $arr[$i + 1],
            "%Y-%m-%d %H:%M:%S");

        my $diff = $nextDateTime - $currentDateTime;
        print($diff->minutes);
    }        
}

Вывод

23 minutes

Вы можете сузить шаблон даты, используя диапазоны (Это по-прежнему не подтверждает это)

\bDate:\h+\K\d{4}-(?:1[0-2]|0?[1-9])-(?:3[01]|[12][0-9]|0?[1-9])\h+(?:2[0-3]|[01]?[0-9]):[0-5]?[0-9]:[0-5]?[0-9]$

Regex demo

0 голосов
/ 30 марта 2020

Желаемый результат может быть достигнут с помощью следующего алгоритма:

Извлечение данных путем просмотра данных для шаблона \bDate: \S+ \S+$ в массив.

Передача массива данных в подпрограмму, которая вычисляет различия между элементами и возвращаемая ссылка на массив результатов (элементы массива представляют га sh с ключами hours,minutes).

Содержимое выходного массива результатов

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

use DateTime::Format::Strptime;

my @data;
my $re = qr/\bDate: (\S+ \S+)$/;

/$re/ && push @data,$1 for <DATA>;

say "$_->{hours}:$_->{minutes}" for @{ time_diff(\@data) };

sub time_diff {
    my $data = shift;
    my @result;

    my $parser = DateTime::Format::Strptime->new(
      pattern => '%Y-%m-%d %H:%M:%S',
      on_error => 'croak',
    );

    for (1..$#data) {
        my $begin = $parser->parse_datetime ( $data->[$_-1] );
        my $end   = $parser->parse_datetime ( $data->[$_]   );
        my $diff  = $end-$begin;

        push @result, { hours => $diff->hours, minutes => $diff->minutes };
    }

    return \@result;
}

__DATA__
ServerName: (DESCRIPTION=(CONNECT_TIMEOUT=60)(RETRY_COUNT=5)(ADDRESS=(PROTOCOL=TCP)(HOST=xbian.dbaas.ing.net)(PORT=121))(CONNECT_DATA=(SERVER=DEDI)(SERVICE_NAME=pmx0))) ServerType: Oracle DatabaseName: MX_FN_OWNER RDBMSAccess: NATIVE_OCI ConnectionName: Mx0_MUXFO_1_1 ConnectionNo: 1  Date: 2020-03-29 08:58:10
insert into MX_FN_OWNER.TRN_EDBF (TIMESTAMP,M_IDENTITY,M_REFERENCE,M_USER,M_GROUP,M_DESK,M_DATE_SYS,M_DATE_CMP,M_TIME_CMP,M_SDATE_CMP,M_STIME_CMP,M_COMMENT,M_ERROR,M_START_END,M_TIME_CPU,M_TIME_SYB,M_TIME_ELAP,M_SCRPT_NAME,M_UNIT_NAME,M_ERR_COUNT,M_NPID) values (0,TRN_EODA_DBFS.nextval,:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18,:19) (Bulk_Copy begin, 19 columns, 1 Flush size)

                              ==============================================
ServerName: (DESCRIPTION=(CONNECT_TIMEOUT=60)(RETRY_COUNT=5)(ADDRESS=(PROTOCOL=TCP)(HOST=xb305-scan.net)(PORT=121))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=pmx02fn))) ServerType: Oracle DatabaseName: MX_FN_OWNER RDBMSAccess: NATIVE_OCI ConnectionName: Mx0_MXFO_168991_1 ConnectionNo: 1  Date: 2020-03-29 09:21:10
Mux execution time: 00:00:00   3 ms 

ServerName: (DESCRIPTION=(CONNECT_TIMEOUT=60)(RETRY_COUNT=5)(ADDRESS=(PROTOCOL=TCP)(HOST=xb305-scan.net)(PORT=121))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=pmx02fn))) ServerType: Oracle DatabaseName: MX_FN_OWNER RDBMSAccess: NATIVE_OCI ConnectionName: Mx0_MXFO_168991_1 ConnectionNo: 1  Date: 2020-03-30 07:11:05
Mux execution time: 00:00:00   3 ms

ServerName: (DESCRIPTION=(CONNECT_TIMEOUT=60)(RETRY_COUNT=5)(ADDRESS=(PROTOCOL=TCP)(HOST=xb305-scan.net)(PORT=121))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=pmx02fn))) ServerType: Oracle DatabaseName: MX_FN_OWNER RDBMSAccess: NATIVE_OCI ConnectionName: Mx0_MXFO_168991_1 ConnectionNo: 1  Date: 2020-03-30 21:49:42
Mux execution time: 00:00:00   3 ms

Выход

0:23
21:49
14:38
0 голосов
/ 29 марта 2020

Попробуйте это

use strict;
use warnings;
use DateTime::Format::Strptime;
my $start_time=time();

my @arr;
my $parser = DateTime::Format::Strptime->new(
  pattern => '%Y-%m-%d %H:%M:%S',
  on_error => 'croak',
);
while (<DATA>)
{
   my $line=$_;
   if($line =~ m/\bDate:\h+\K\d{4}-\d{2}-\d{2}\h+\d{2}:\d{2}:\d{2}$/) {
      push (@arr,$&);
   }
}

for my $i (0 .. $#arr) {
    if (exists($arr[$i + 1])) {
        my $currentDateTime =  $parser->parse_datetime ($arr[$i]);
        my $nextDateTime =  $parser->parse_datetime ($arr[$i + 1]);
        my $diff = $nextDateTime - $currentDateTime;
        print($diff->hours,":",$diff->minutes );
        print "\n";
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...