2011-07-15 9 views
5

Chcę przeszukać wiersze pliku, aby sprawdzić, czy którekolwiek z nich pasuje do jednego z zestawu wyrażeń regularnych.Skąd wiadomo, która część wyrażeń regularnych Perla jest dopasowana przez ciąg znaków?

coś takiego:

my @regs = (qr/a/, qr/b/, qr/c/); 
foreach my $line (<ARGV>) { 
    foreach my $reg (@regs) { 
     if ($line =~ /$reg/) { 
     printf("matched %s\n", $reg); 
     } 
    } 
} 

ale może to być powolne.

Wygląda na to, że kompilator regex mógłby pomóc. Czy jest optymalizacja tak:

my $master_reg = join("|", @regs); # this is wrong syntax. what's the right way? 
foreach my $line (<ARGV>) { 
    $line =~ /$master_reg/; 
    my $matched = special_function(); 
    printf("matched the %sth reg: %s\n", $matched, $regs[$matched] 
} 

}

gdzie „special_function” jest specjalny sos mówi mi, który został dopasowany część regex.

Odpowiedz

8

Użyj przechwytywania nawiasów. Podstawowa idea wygląda następująco:

my @matches = $foo =~ /(one)|(two)|(three)/; 
defined $matches[0] 
    and print "Matched 'one'\n"; 
defined $matches[1] 
    and print "Matched 'two'\n"; 
defined $matches[2] 
    and print "Matched 'three'\n"; 
5

Add przechwytywanie grupy:

"pear" =~ /(a)|(b)|(c)/; 
if (defined $1) { 
    print "Matched a\n"; 
} elsif (defined $2) { 
    print "Matched b\n"; 
} elsif (defined $3) { 
    print "Matched c\n"; 
} else { 
    print "No match\n"; 
} 

Oczywiście w tym prostym przykładzie mogłeś używane /(a|b|c)/ równie dobrze i po prostu wydrukowany $1, ale gdy 'a', „b ", a" c "może być dowolnie złożonymi wyrażeniami, jest to wygrana.

Jeśli budowanie regex programowo może okazać się bolesny musiał użyć numerowane zmienne, więc zamiast zerwania surowość, patrzeć w @- lub @+ tablic, które zawierają zamiast przesunięcia pozycji dla każdego meczu. $-[0] jest zawsze ustawiony, o ile wzorzec jest zgodny, ale wyższy $-[$n] będzie zawierał tylko określone wartości, jeśli pasująca grupa przechwytująca n pasuje.

Powiązane problemy