#regex #perl
#регулярное выражение #perl
Вопрос:
У меня есть массив @WIALOG_lines с записями ниже
(0552) -*--@ "<No comment>" 27-Oct-2020 10:40 AM
(0553) M---$ user1 100900 "Random job
(0554) ----@ 1119996 "patch content"
(0562) -*--@ "<No comment>" 24-Oct-2020 10:40 AM
Мне нужно иметь 0552,0553,0554 и 0562 в этом массиве. Я пробую приведенную ниже команду и не работает. Можете ли вы помочь с регулярным выражением, чтобы получить значения, заключенные только в круглые скобки.
s/(^[^(] ")|("[^)] )//g for @WIALOG_lines;
Комментарии:
1. Что вы пробовали? С какой проблемой вы столкнулись?
2. Обновил вопрос тем, что я пробовал
Ответ №1:
Мы хотим сопоставить числа между первым набором круглых скобок. Этот шаблон представляет собой открытую пару, любое количество символов, которые не являются закрывающей парой, и конечную пару. И мы хотим захватить символы между круглыми скобками. Круглые скобки являются особыми в регулярных выражениях, поэтому их нужно экранировать. Этот шаблон регулярного выражения: m/(([^)]*))/
, где экранированные круглые скобки совпадают буквально, а другая пара круглых скобок представляет собой группу захвата.
Затем мы хотим применить этот шаблон к каждой строке исходного массива, что предполагает использование блока карты. Для каждого элемента исходного массива выполните сопоставление и верните соответствующую часть. $1
будет строка, которая соответствует первой группе захвата.
my @key = map { m/(([^)] ))/; $1 } @WIALOG_lines;
Комментарии:
1. @Ras Вы читаете файл построчно или переводите файл в одну переменную
2. TLP, я читаю построчно. Все, что я пропустил, вставляя новые записи в @WIALOG_lines. Теперь у меня все хорошо.
3.
map { m/(([^)] ))/ }
достаточно хорошо. На самом деле, это лучше, потому что оно добавляетundef
для строк, которые не совпадают
Ответ №2:
Решение опубликованного вопроса, как было указано ранее, легко реализовать, заключив цифры в квадратные скобки, чтобы сохранить их в массиве для дальнейшей обработки.
use strict;
use warnings;
use feature 'say';
my @keys = map { $1 if /^((d ))/ } <DATA>;
say for @keys;
__DATA__
(0552) -*--@ "<No comment>" 27-Oct-2020 10:40 AM
(0553) M---$ user1 100900 "Random job
(0554) ----@ 1119996 "patch content"
(0562) -*--@ "<No comment>" 24-Oct-2020 10:40 AM
Более интересным случаем было бы, если бы входные данные требовали некоторого дополнительного синтаксического анализа. Следующий пример демонстрирует этот подход.
ПРИМЕЧАНИЕ: входные данные для записи с меткой 0553 отсутствуют закрытие "
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my %log;
while( <DATA> ) {
chomp;
my @col = /((d ))s (S )s (.*)z/;
my $data;
if( $col[2] =~ /(.*) (d{2}-w{3}-d{4}) (d{2}:d{2}) (w{2})z/ ) {
$data = { comment => $1, date => $2, time => $3, AM => $4 };
} else {
$data = { user => $1 , label => $2, desc => $3 } if $col[2] =~ /(S ) (d ) (".*?"?)z/;
$data = { label => $1, desc => $2 } if $col[2] =~ /(d ) (".*?")z/;
}
$log{$col[0]} = { perm => $col[1], data => $data };
}
say Dumper(%log);
__DATA__
(0552) -*--@ "<No comment>" 27-Oct-2020 10:40 AM
(0553) M---$ user1 100900 "Random job
(0554) ----@ 1119996 "patch content"
(0562) -*--@ "<No comment>" 24-Oct-2020 10:40 AM
Вывод
$VAR1 = {
'0562' => {
'perm' => '-*--@',
'data' => {
'date' => '24-Oct-2020',
'AM' => 'AM',
'comment' => '"<No comment>"',
'time' => '10:40'
}
},
'0553' => {
'perm' => 'M---$',
'data' => {
'desc' => '"Random job',
'user' => 'user1',
'label' => '100900'
}
},
'0552' => {
'perm' => '-*--@',
'data' => {
'date' => '27-Oct-2020',
'time' => '10:40',
'AM' => 'AM',
'comment' => '"<No comment>"'
}
},
'0554' => {
'data' => {
'label' => '1119996',
'desc' => '"patch content"'
},
'perm' => '----@'
}
};