2009-06-03 3 views
8

Возможно ли обнаружение повторяющихся шаблонов чисел с регулярным выражением?Регулярное выражение для обнаружения повторения внутри строки

Так, например, если бы у меня была следующая строка «034503450345», можно ли было бы соответствовать повторяющейся последовательности 0345? У меня такое чувство, что это выходит за рамки регулярного выражения, но я думал, что попрошу здесь все равно посмотреть, не пропустил ли я что-нибудь.

+1

какой язык/платформу вы используете? –

+0

Я использую C#. Все, что мне было нужно, это регулярное выражение, поэтому я реализовал решение RichieHindle и уже проверял его на основе моих тестовых данных! Я также многому научился у превосходно прокомментированного регулярного выражения Питера Боутона. Спасибо вам обоим! –

+0

@MarkWithers Я занимаюсь тем же вопросом. Не могли бы вы быть более конкретными и рассказать мне больше о вашем решении? Спасибо – user2179427

ответ

9

Да, вы можете - вот тест Python случае

import re 
print re.search(r"(\d+).*\1", "8034503450345").group(1) 
# Prints 0345 

Регулярное выражение говорит «найти последовательность цифр, то любое количество других вещей, то та же последовательность снова.»

На едва связанной ноте, вот одна из моих любимых регулярных выражений - простой детектор номер:

import re 
for i in range(2, 100): 
    if not re.search(r"^(xx+)\1+$", "x"*i): 
     print i 
+0

Ваш детектив с числовым числом находит 0 и 1, чтобы быть простым :-) – balpha

+0

Any идея, почему следующий пример: * только * соответствует '8', а не' 0345'? В работе [18]: Foo = re.search (г "(\ D +) * \ 1", "+80345824103452420345") В работе [19]: foo.groups() Out [19]: ('8 ',) –

+0

@balpha: Хороший pont - исправлен. 8-) – RichieHindle

19

Это выражение будет соответствовать один или несколько повторяющихся групп:

(.+)(?=\1+) 


Здесь одно и то же выражение разбито, (используя комментирование, чтобы он мог использоваться непосредственно как регулярное выражение).

(?x) # enable regex comment mode 
( # start capturing group 
.+ # one or more of any character (excludes newlines by default) 
)  # end capturing group 
(?= # begin lookahead 
\1+ # match one or more of the first capturing group 
)  # end lookahead 


Для того, чтобы соответствовать определенному образцу, изменить .+ к этому шаблону, например, \d+ для одного или нескольких номеров, или \d{4,}, чтобы соответствовать 4 или более номерам.

Чтобы соответствовать определенному числу шаблонов, измените \1+, например, на \1{4} на четыре повторения.

Чтобы повторение не было рядом друг с другом, вы можете добавить .*? внутри lookahead.

+1

Отличное объяснение +1 – ichiban

+0

Хороший пример, объяснил очень хорошо –

+0

Отличное объяснение. Отличное расширение. Благодаря!! +1 – Toto

8

Просто, чтобы добавить примечание к (правильный) ответ от RichieHindle:

Обратите внимание, что при реализации регулярных выражений в Python (и многие другие, например, в Perl) может это сделать, это уже не является регулярным выражением в узкий смысл слова.

Ваш пример не является обычным языком, поэтому не может обрабатываться чистое регулярное выражение. См. отличный Wikipedia article для деталей.

Хотя это в основном только академический интерес, есть некоторые практические последствия. Реальные регулярные выражения могут значительно улучшить гарантии максимального времени автономной работы, чем в этом случае. Поэтому в какой-то момент вы можете получить проблемы с производительностью.

Нельзя сказать, что это нехорошее решение, но вы должны понимать, что находитесь на пределе того, на что способны регулярные выражения (даже в расширенной форме), и могут захотеть рассмотреть другие решения в случае проблем ,

+0

Очень интересное чтение, спасибо за это. –

2

Это код C#, который использует конструкцию обратной ссылки для поиска повторяющихся цифр. Он будет работать с 034503450345, 123034503450345, 034503450345345, 232034503450345423. Регулярное выражение намного проще и понятнее.

/// <summary> 
/// Assigns repeated digits to repeatedDigits, if the digitSequence matches the pattern 
/// </summary> 
/// <returns>true if success, false otherwise</returns> 
public static bool TryGetRepeatedDigits(string digitSequence, out string repeatedDigits) 
{ 
    repeatedDigits = null; 

    string pattern = @"^\d*(?<repeat>\d+)\k<repeat>+\d*$"; 

    if (Regex.IsMatch(digitSequence, pattern)) 
    { 
     Regex r = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); 
     repeatedDigits = r.Match(digitSequence).Result("${repeat}"); 
     return true; 
    } 
    else 
     return false; 
} 
+0

Очень приятно! Мне нравится использование названной группы. Код качества продукции, прокомментированный и готовый к копированию. Огромное спасибо! –

+0

«Готов к скопированию»: D .. Мне это нравится !!!! –

0

Использование регулярных выражений повторения: бар {2} выглядит для текста с двумя или более бар: Barbar barbarbar ...