2013-11-24 2 views
0

Предположим, у меня есть 2 шаблона регулярных выражений [\d\d] и [a-zA-Z][a-zA-Z], и я хочу проверить, имеет ли строка эти шаблоны в любом количестве и в любом порядке, и только те шаблоны, разделенные запятой, как я могу это сделать с perl?совпадение двух шаблонов с регулярным выражением perl

  • , например, строки ex,xy,gf,55,66-> match

  • например строки 22,24,25,56,ff ->match

  • например строки 2FF,24,25,56,ff -> not match

+3

Соответствие действительности: '2f'? –

+0

'\ w' уже содержит числа '\ d', что означает, что вы также можете получать смешанные совпадения букв и цифр, например, один Тим, упомянутый выше' 2f'. Вам нужно решить, является ли это действительным совпадением. Кроме того, '[\ d \ d]' является избыточным выражением, которое упрощается до '\ d'. – TLP

+0

Нет его недействительного соответствия только тем, что я имею в виду, я пересмотрел quesition – smith

ответ

2

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

^(([A-Za-z]{2}|\d\d),)*([A-Za-z]{2}|\d\d)$ 

Tested on regexe

Получили следующий результат:

Result

+0

Скобки, расположенные непосредственно вокруг '\ d \ d', являются излишними, иначе +1. –

1
#!/usr/bin/perl 
use warnings; 
use strict; 

my $pattern1 = '\d'; 
my $pattern2 = '[a-zA-Z]'; 
my $string = ('ex,xy,gf,55,66'); 
my $warning = 0; 

my @split = split(/,/, $string); 
foreach (@split){ 
    unless (($_ =~ /^$pattern1{2}$/) or ($_ =~ /^$pattern2{2}$/)) { 
     $warning++; 
    } 
} 

print "$string -> match\n" if ($warning == 0); 
print "$string -> no match" if ($warning != 0); 

Выходы:

ex,xy,gf,55,66 -> match 

же код, другая строка:

my $string = ('22,2f,ex,xy,gf,2FF'); 

Выходы:

22,2f,ex,xy,gf,2FF -> no match 
0

Вот вариант использования /^(?:[a-z]{2},?|\d\d,?)+$/i:

use strict; 
use warnings; 

while (<DATA>) { 
    chomp; 
    my @elems = split /,/; 
    my @match = grep /^(?:\d{2}|[a-z]{2})$/i, @elems; 
    print "$_ -> ", (@elems == @match ? '' : 'not '), "match\n" 
} 

__DATA__ 
ex,xy,gf,55,66 
22,24,25,56,ff 
2FF,24,25,56,ff 

Выход:

ex,xy,gf,55,66 -> match 
22,24,25,56,ff -> match 
2FF,24,25,56,ff -> not match 

Надеюсь, это поможет!

+0

Предоставление дополнительных запятых позволяет использовать строки типа 'aaaa' или' 22aa' (длина делится на 2). – TLP

+0

@TLP - Спасибо за вызов regex-problem. Перепроверили мое первоначальное решение. – Kenosis

0

Вы можете использовать это:

^((?>[a-z]{2}|[0-9]{2})(?>,(?1)|$)) 

или это:

^(?>(?>[a-z]{2}|[0-9]{2})(?>,|$))+$ 
0

После игры вокруг с этим в Perl, я придумал это.
Я тестировал все ответы, размещенные на Perl. Проблемы возникают из-за попытки сопоставления
очень большие строки. В основном из них> 256 К. Перл, похоже, не находит ни одного матча, где на
меньший размер. Возможно, это настройка, которую я не использую, я не знаю ..
Исключением было рекурсивное регулярное выражение Казимира, которое занимает минуту, чтобы соответствовать 3-мегабуферу.

Итак, для усмешек я собрал регулярное выражение, соответствующее отрицанию того, что разрешено.
Буфер на 15 мегабайт занимает максимум 10 секунд на моей машине в зависимости от того, где ошибка (совпадение)
была или 10 секунд, если она пройдет.Примечательно, что нет накопления
информация о захвате, возможно, поэтому она может обрабатывать большие буферы.

$test = "ex,xy,gt,55,66,"; 
for (0 .. 19) { $test .= $test; } 
$test .= "3a3"; 

print "\nlength = ", length($test), "\n------------\n"; 

if ($test =~ m/ 

    # \d(?:[a-z]|\d{2})|[a-z](?:\d|[a-z]{2})|[^a-z\d,]|,(?:.?,|$)|^, 

     \d 
     (?: [a-z] | \d{2}) 
    | 
     [a-z] 
     (?: \d | [a-z]{2}) 
    | 
     [^a-z\d,] 
    | 
     , 
     (?: .? , | $) 
    | 
    ^, 

/xg) 

{ print "Found error at pos = ", pos($test), "\n"; } 
else 
{ print "Passed test!\n"; } 

__END__ 

Output >> 

length = 15728643 
------------ 
Found error at pos = 15728642 
Смежные вопросы