Perl вырезать символы до вращающегося регулярного выражения, печатать до конца строки - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть эти данные, где я хочу вырезать дату и распечатать все от инициалов до конца. Я нанес на карту инициалы.

30th Mar 2020 5:53:18 pm Charlie Brown: BJ: Bloomberg Runs
30th Mar 2020 5:53:27 pm Charlie Brown: DS: ICE DATA = INC1018483661
30th Mar 2020 6:42:43 pm Boris Yeltsin: Cortese's ICE logs is for the Bloomberg Runs issue
30th Mar 2020 6:43:28 pm Charlie Brown: yeap
31st Mar 2020 4:11:22 am Ishtar Johnson: VK : RE: XS2018777099 & XS2018777172 - INC1018491954
31st Mar 2020 6:31:17 am Tommy Boy: NW: RE: SABSM 6.125 YTW - INC1018495843
31st Mar 2020 7:26:40 am Tommy Boy: AP: RE: Rolling 7yrs - INC1018497102
31st Mar 2020 7:45:36 am Tommy Boy: JK: RE: Chris White books - INC1018497380

Вот код -

#!/usr/bin/perl

use strict;
use warnings;

my @team = ("AP","II","DS","WJ", "JK","LC","BJ") ;
my ( $team_regex ) = map {qr /$_/} join "|", map {quotemeta} @team;

my @orderdTeam ;
my $filename = shift @ARGV ;
open(my $fh, '<', $filename) or die "Could not open file $filename $!";
while (my $line = <$fh> ) {
        #$line =~ /($team_regex .*)/s  ;
        $line = /($team_regex .*)/s  ;
        print "$line\n";

}
close $fh;

По какой-то причине я получаю эти неинициализированные ошибки.

johnswal@NYKPWM2037968 ~
$ ./cut_date_symphony.pl fooberry
Use of uninitialized value $_ in pattern match (m//) at ./cut_date_symphony.pl line 14, <$fh> line 1.
Use of uninitialized value $_ in pattern match (m//) at ./cut_date_symphony.pl line 14, <$fh> line 2.
Use of uninitialized value $_ in pattern match (m//) at ./cut_date_symphony.pl line 14, <$fh> line 3.
Use of uninitialized value $_ in pattern match (m//) at ./cut_date_symphony.pl line 14, <$fh> line 4.
Use of uninitialized value $_ in pattern match (m//) at ./cut_date_symphony.pl line 14, <$fh> line 5.
Use of uninitialized value $_ in pattern match (m//) at ./cut_date_symphony.pl line 14, <$fh> line 6.
Use of uninitialized value $_ in pattern match (m//) at ./cut_date_symphony.pl line 14, <$fh> line 7.
Use of uninitialized value $_ in pattern match (m//) at ./cut_date_symphony.pl line 14, <$fh> line 8.

Закомментированная строка просто печатает всю строку - она ​​не вырезает дату или время

#$line =~ /($team_regex .*)/s  ;

Так вот, что я ищу. «Tommy Boy NW:» и «Ishtar Johnson VK:» являются частью нашей команды, но из Европы. Только члены американской команды в массиве карт «@team_regex» будут отображаться билеты. и время и дата будут вырезаны из строки.

BJ: Bloomberg Runs
DS: ICE DATA = INC1018483661
AP: RE: Rolling 7yrs - INC1018497102
JK: RE: Chris White books - INC1018497380

Ответы [ 2 ]

4 голосов
/ 08 апреля 2020

Строка 14 - это строка:

$line = /($team_regex .*)/s  ;

Оператор соответствия (/.../) работает либо с переменной, связанной с ним, с помощью оператора =~, либо с $_, если такой переменной нет дано. Вы не используете =~, поэтому оператор сопоставления пытается сопоставить с $. И $_ не содержит данных, поэтому Perl выдает предупреждение «неопределенное значение», которое вы видите.

Я думаю, вы хотите сопоставить регулярное выражение с содержимым $line. Поэтому вам нужно использовать =~ вместо = - как в вашей закомментированной строке.

$line =~ /($team_regex .*)/s  ;

Но в комментарии выше вы поясните, что вы закомментировали это, потому что:

Закомментированная строка не вырезает никаких символов - она ​​печатает весь код

И, конечно, это происходит потому, что вы не написали код для изменения $line в любом случае. , Но то, что вы хотите, находится в $1 после совпадения, поэтому выведите его вместо этого.

$line =~ /($team_regex .*)/s  ;
print $1;

Но переменные регулярного выражения, такие как $1, устанавливаются только при успешном сопоставлении, поэтому важно проверить совпадение работает до их распечатки. Вы можете сделать это, поместив оператор сопоставления в оператор if.

if ($line =~ /($team_regex .*)/s) {
  print $1;
}

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

if ($line =~ /($team_regex:.*)/s) {
  print $1;
}
1 голос
/ 08 апреля 2020

Пожалуйста, посмотрите следующий фрагмент кода для демонстрации того, как достичь желаемого результата

Я считаю, что регулярное выражение для команды должно быть сформировано по-другому. Пропустить все записи, не соответствующие регулярному выражению. Затем замените первые 5 столбцы данных на пустые и напечатайте результат.

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

my @team = ("AP","II","DS","WJ", "JK","LC","BJ");

my $re_team = join ': |', @team;

my $filename = shift;

open(my $fh, '<', $filename)
    or die "Could not open file $filename $!";

while( <$fh> ) {
    chomp;
    next unless /$re_team/;
    s/^(\S+ ){5}//;
    say;
}

close $fh;

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

30th Mar 2020 5:53:18 pm Charlie Brown: BJ: Bloomberg Runs
30th Mar 2020 5:53:27 pm Charlie Brown: DS: ICE DATA = INC1018483661
30th Mar 2020 6:42:43 pm Boris Yeltsin: Cortese's ICE logs is for the Bloomberg Runs issue
30th Mar 2020 6:43:28 pm Charlie Brown: yeap
31st Mar 2020 4:11:22 am Ishtar Johnson: VK : RE: XS2018777099 & XS2018777172 - INC1018491954
31st Mar 2020 6:31:17 am Tommy Boy: NW: RE: SABSM 6.125 YTW - INC1018495843
31st Mar 2020 7:26:40 am Tommy Boy: AP: RE: Rolling 7yrs - INC1018497102
31st Mar 2020 7:45:36 am Tommy Boy: JK: RE: Chris White books - INC1018497380

Вывод

Charlie Brown: BJ: Bloomberg Runs
Charlie Brown: DS: ICE DATA = INC1018483661
Tommy Boy: AP: RE: Rolling 7yrs - INC1018497102
Tommy Boy: JK: RE: Chris White books - INC1018497380

Замена * От 1014 * до s/^(\S+ ){7}//;, чтобы получить следующий вывод

BJ: Bloomberg Runs
DS: ICE DATA = INC1018483661
AP: RE: Rolling 7yrs - INC1018497102
JK: RE: Chris White books - INC1018497380

Конечно, код можно записать как

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

my @team = ("AP","II","DS","WJ", "JK","LC","BJ");

my $re_team = join ': |', @team;

my $filename = shift;

open(my $fh, '<', $filename)
    or die "Could not open file $filename $!";

/($re_team)/ && say /($1.*)/  while <$fh>;

close $fh

Или даже так

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

my @team = ("AP","II","DS","WJ", "JK","LC","BJ");

my $re_team = join ': |', @team;

/($re_team)/ && say /($1.*)/  while <>;

Вывод

BJ: Bloomberg Runs
DS: ICE DATA = INC1018483661
AP: RE: Rolling 7yrs - INC1018497102
JK: RE: Chris White books - INC1018497380

Если необходимо захватить данные

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

use Data::Dumper;

my @team = ("AP","II","DS","WJ", "JK","LC","BJ");

my $re_team = join ': |', @team;

my @data;

/($re_team)/ && push @data,/($1.*)/  while <>;

say Dumper(\@data);

Вывод

$VAR1 = [
          'BJ: Bloomberg Runs',
          'DS: ICE DATA = INC1018483661',
          'AP: RE: Rolling 7yrs - INC1018497102',
          'JK: RE: Chris White books - INC1018497380'
        ];
...