2016-03-03 6 views
3

Так что это, вероятно, имеет очень простое решение, но я довольно зеленый в Perl .... Для простоты я буду использовать простой пример:Динамически добывающие несколько частей строки Perl/Regex

# extract hours, minutes, seconds 
$time =~ /(\d\d):(\d\d):(\d\d)/; # match hh:mm:ss format 
$hours = $1; 
$minutes = $2; 
$seconds = $3; 

Приложение, которое я пишу, позволяет пользователю вводить строку регулярных выражений, которая может иметь несколько совпадений, как в примере. Я ищу способ узнать, сколько $<n> доступны для меня на основе регулярного выражения, введенного пользователем. Есть ли способ увидеть, были ли определены $ 1, $ 2 .... $ n во время текущего процесса сопоставления? Я использую: $parsed_response =~ /$block_start_regex/; где $ block_start_regex может быть что-то вроде $block_start_regex=qr/(\S+)\s+(\S+)\s+(\S+)/; или любого другого пользователя вводит .....

Кроме того, если я сопрягать ранее в коде на 9 переменных, все они устанавливают к неопределенному в следующий раз, когда я запустим регулярное выражение?

ответ

5

Если вы сопоставление регулярного выражения, вы можете захватить «спичку» в массив:

my @matches = $time =~ /(\d\d):(\d\d):(\d\d)/g; 

Это будет соответствовать несколько раз, и Плонк «попадет» в к @matches массиву.

Так взять приведенный выше пример:

#!/usr/bin/env perl 
use strict; 
use warnings; 
use Data::Dumper; 

my $str = "11:22:33 somefhunakdawer 14:32:17"; 

my @matches = $str =~ /(\d\d):(\d\d):(\d\d)/g; 

print Dumper \@matches; 

Это даст вам массив с:

$VAR1 = [ 
      '11', 
      '22', 
      '33', 
      '14', 
      '32', 
      '17' 
     ]; 

Хотя - вы должны прочитать вам массив в 3-элементных куски.

В качестве альтернативы - вы можете «группы» ваш захват, в зависимости точно, что вы после:

my $str = "11:22:33 somefhunakdawer 14:32:17"; 
my $pattern = qr/(\d\d):(\d\d):(\d\d)/; 

my @matches = $str =~ m/($pattern)/g; 

print Dumper \@matches; 

Это даст вам:

$VAR1 = [ 
      '11:22:33', 
      '11', 
      '22', 
      '33', 
      '14:32:17', 
      '14', 
      '32', 
      '17' 
     ]; 

Это немного трудно принять вход шаблон и «слияние», но вы могли бы сделать что-то вроде:

my $str = "11:22:33 somefhunakdawer 14:32:17"; 
my $pattern = qr/\d\d:\d\d:\d\d/; 

my @matches = map {[ split /:/ ]} $str =~ m/($pattern)/g; 

print Dumper \@matches; 

Это выбирает экземпляры $pattern, но затем использует map, чтобы разделить его на разделитель, в подматрицу. Таким образом, мы получаем:

$VAR1 = [ 
      [ 
      '11', 
      '22', 
      '33' 
      ], 
      [ 
      '14', 
      '32', 
      '17' 
      ] 
     ]; 

В обоих случаях, хотя, вам нужно немного больше логики к этому - вы можете сказать, если у вас есть 3 захвата группы в вашем входе, вы будете иметь кратные 3 в ваш @matches.

Если вы хотите, чтобы динамически обнаружить, вы могли бы, вероятно, двойной матч:

my $str = "11:22:33 somefhunakdawer 14:32:17"; 
my $pattern = qr/(\d\d):(\d\d):(\d\d)/; 

my @matches = $str =~ m/$pattern/; 
my $num_groups = @matches; 
@matches = $str =~ m/$pattern/g; 

while (@matches) { 
    print "Group : ", join ("-", splice (@matches, 0, $num_groups)),"\n"; 
} 

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

Затем вы запускаете второй захват - с g - чтобы повторить захват в массиве, а затем извлеките несколько групп захвата из списка совпадений.

Хотя примечание - этот подход не сработает, если в шаблоне ввода есть группы с переменным захватом - например,

my $pattern = qr/(\d{2}):(\d{2})(?::(\d{2}))?/; 

который имеет ТИнструкциям секундная матч

+0

Да, просто хранить их в массиве дал мне достаточно, чтобы использовать мои базовые знания PERL, чтобы заставить его работать. Другие методы группировки и захвата очень образовательны, спасибо! –

Смежные вопросы