2015-09-29 9 views
7

Люди, Я пытаюсь использовать регулярные выражения для обработки большого набора строк чисел и сопоставления последовательностей цифр для определенных шаблонов, где некоторые цифры повторяется в группах. Часть требования заключается в обеспечении уникальности между разделами данного шаблона.regex, сопоставляющий две группы повторяющихся цифр, где обе не могут быть одинаковыми цифрами

Примером подобного сращивания я пытаюсь достичь

ABBBCCDD 

Интерпретировать это как набор цифр. Но A, B, C, D не могут быть одинаковыми. И повторение каждого - это образец, который мы пытаемся сопоставить.

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

Так обратиться ABBBCCDD я придумал это RE с помощью отрицательных смотреть вперед, используя группу ..

(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1} 

Чтобы разорвать этот вниз ..

(.)   single character wildcard group 1 (A) 
(?!\1{1,7}) negative look-ahead for 1-7 occurrences of group 1 (A) 
(.)   single character wildcard group 2 (B) 
\2{2}   A further two occurrences of group 2 (B) 
(?!\2{1,4}) Negative look-ahead of 1-4 occurrences of group 2 (B) 
(.)   single character wildcard group 3 (C) 
\3{1}   One more occurrence of group 3 (C) 
(?!\3{1,2}) Negative look-ahead of 1-2 occurrences of group 3 (C) 
(.)   single character wildcard group 4 (D) 
\4{1}   one more occurrence of group 4 (D) 

мыслящие здесь является то, что негативным взгляды на будущее действуют как средство проверки того, что данный символ не найден там, где это неожиданно. Таким образом, A проверяется в следующих 7 символах. После того, как B и 2 повторения совпадают, мы отрицательно смотрим вперед на B в следующих четырех символах. Наконец, как только пара Cs сопоставлена, мы смотрим в финале 2 для C как средство обнаружения несоответствия.

Для данных теста эта строка «01110033» соответствует выражению. Но это не должно потому, что «0» для А повторяется в позиции «С».

Я проверил проверки этого выражения на Python и grep в режиме PCRE (-P). Оба соответствуют неправильному шаблону.

Я положил выражение в https://regex101.com/ вместе с той же тестовой строкой «01110033», и оно также соответствовало этому. У меня недостаточно рейтинга для публикации изображений этого или вариантов, которые я пробовал с тестовыми данными. Так вот некоторые текстовые грейферы из командной строки выполняются с Grep -P

Таким образом, наше недействительно выражение, которое повторяет в CC позиция получает через ..

$ echo "01110033" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}' 
01110033 
$ 

Изменения DD 11, копирование ГЭБА, мы также считают, что получает через несмотря на B, имеющий передний отрицательный чек ..

$ echo "01110011" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}' 
01110011 
$ 

Теперь измените DD до «00», копируя CC цифр и низкий, и вот он не соответствует ..

$ echo "01110000" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}' 
$ 

Удалите передний-отрицательный чек для CC "(?! \ 3 {1,2})" из выражения, и наш повтор цифры C в позиции D прорвется.

$ echo "01110000" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(.)\4{1}' 
01110000 
$ 

Назад к оригинальному номеру испытания и переключатель CC цифр в то же использование «1» из B. Она не достучаться.

$ echo "01111133" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}' 
$ 

И играть это для группы В, установите B цифру к тому же 0, как встречается для А. также не соответствуют ..

$ echo "00002233" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}' 
$ 

Затем выньте отрицательный предпросмотр для а и мы можем это, чтобы соответствовать ..

$ echo "00002233" | grep -P '(.)(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}' 
00002233 
$ 

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

Если добавить дополнительный предпросмотр на праве после B и его повторение были обработаны, мы получаем его, чтобы избежать согласований на CC части повторного использования А цифра ..

$ echo "01110033" | grep -P '(.)(?!\1{1,7})(.)\2{2}(?!\1{1,4})(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1}' 
$ 

Для того, чтобы это дальше, то после согласования набора CC мне нужно будет снова повторить негативные образы для A и B. Это просто кажется неправильным.

Надеюсь, эксперт RE может прояснить то, что я делаю неправильно здесь или подтвердить, если отрицательна-предпросмотр действительно ограничивается на основании того, что я наблюдая

ответ

0
(.)(?!.{0,6}\1)(.)\2{2}(?!\2{1,4})(.)\3{1}(?!\3{1,2})(.)\4{1} 

    ^^^^^^^^ 

Изменение lookahead, чтобы запретить матч, когда \1 появляется в любом месте в строке. См. демонстрацию. Аналогичным образом вы можете изменять и другие части в своем регулярном выражении.

https://regex101.com/r/vV1wW6/31

+0

Спасибо за это. Это будет специально работать для примера, который я показал. Некоторые из более сложных шаблонов, однако, будут повторять A, B, C, D позже в последовательности. Но на основании вашего ответа я просто обнаружил, что использование .. (?!. {0,6} \ 1) также будет работать как средство тестирования моей группы в следующих 7 символах путем подачи его в виде 0-6 подстановочных знаков по моему групповому характеру. Поэтому я сейчас буду работать с этим подходом. Еще раз спасибо за быстрый ответ. –

0

Примечание: обновлен.

Как уже отмечалось, ваши негативные взгляды не исключали то, что вы думали - например, \1{1,7} только исключает A, AA, AAA, AAAA, AAAAA, AAAAAA и AAAAAAA. Я думаю, что вы хотите lookaheads быть .*\1, .*\2, .*\3 и т.д.

Но вот еще одна идея: Легко предварительной фильтрации из любой линии, которая имеет несмежные повторяющиеся символы:

grep -P -v '(.)(?!\1).*\1' 

и тогда ваш регулярное выражение на результат гораздо проще: .{1}.{3}.{2}.{2}

И на самом деле все это может сочетаться с использованием первой в качестве отрицательного предварительного опережения ограничения:

(?!.*(.)(?!\1).*\1).{1}.{3}.{2}.{2} 

Или, если вам нужно, чтобы захватить цифры, как вы делали первоначально:

(?!.*(.)(?!\1).*\1)(.){1}(.){3}(.){2}(.){2} 

Но обратите внимание, что эти цифры теперь будут \ 2 \ 3 \ 4 \ 5, так как \ 1 в упреждающей выборке.

+1

Спасибо за это уточнение. Есть набор из более чем 50 шаблонов, которые мне нужно сопоставить, и они идут повсюду с шаблонами. В некоторых случаях один и тот же символ будет повторен далее. Таким образом, мне пришлось изменить решение vks, чтобы быть (?!. {0,6} \ 1), который будет тестировать 0-6 диких, а затем \ 1 в качестве замены того, что я думал \ 1 {1,7} должен сделать для меня. И другие выражения тогда просто стали вариантами того же трюка –

+0

Добро пожаловать. Это то, что вам нужно, - контур проблемного пространства _complete_, который вам нужен, прежде чем можно будет найти какое-либо общее правильное решение. И если это действительно «повсюду с шаблонами», общее решение не существует - вам придется делать это по частям. –

0

Основываясь на отзывах до сих пор, я даю еще один ответ, который не полагается на выполнение арифметики на основе общей длины и которая будет самостоятельно идентифицировать любую последовательность из 4 уникальных групп символов/цифр в последовательности длины 1, 3,2,2 в любом месте в строке:

/(?<=^|(.)(?!\1))(.)\2{0}(?!\2)(.)\3{2}(?!\2|\3)(.)\4{1}(?!\2|\3|\4)(.)\5{1}(?!\5)/gm 
^^^^^^^^^^^^^^^^ this is a look-behind that makes sure we're starting with a new character/digit 
       ^^^^^^^^ this is the size-1 group; yes the \2{0} is superfluous 
         ^^^^^^ this ensures the next group is unique 
           ^^^^^^^^ this is the size-3 group 
etc. 

Сообщите мне, если это ближе к вашему решению. Если это так, и если все ваши «шаблоны» состоят из последовательностей размеров групп, которые вы ищете (например, 1,3,2,2), я могу придумать некоторый код, который будет генерировать соответствующее регулярное выражение для любого такого ввод «шаблон».

0

только некоторые подробности здесь о том, что в конечном итоге решение выглядело как для меня ..

Так фундаментально (?! \ 1 {1,7}) не то, что я думал, что это было бы и была вся причина о проблемах, с которыми я столкнулся. Искренне благодарю вас, ребята, за то, что вы нашли для меня эту проблему.

Пример, который я показал, был 1 из примерно 50 лет, я должен был сформулировать из набора узоров.

Это закончилось, как ..

ABBBCCDD 
09(.)(?!.{0,6}\1)(.)\2{2}(?!.{0,3}\2)(.)\3{1}(?!.{0,1}\3)(.)\4{1} 

Так как только \ 1 (А) был взят в плен, я испытал отрицательный предпросмотр 0-6 wildchars предшествовавших А. Тогда я захвачу \ 2 (В), его два повторений, а затем дать B отрицательный результат 0-3 диких + B и так далее.

Он удерживает фокус, ориентированный на перспективу негативно, чтобы убедиться, что пойманные группы не повторяются там, где они не должны. Затем последующие захваты и их повторяющиеся шаблоны сделают все остальное в обеспечении соответствия.

Другие примеры из конечного набора:

ABCCDDDD 
(.)(?!.{0,6}\1)(.)(?!.{0,5}\2)(.)\3{1}(?!.{0,3}\3)(.)\4{3} 

AABBCCDD 
(.)\1{1}(?!.{0,5}\1)(.)\2{1}(?!.{0,3}\2)(.)\3{1}(?!.{0,1}\3)(.)\4{1} 

ABCCDEDE 
09(.)(?!.{0,6}\1)(.)(?!.{0,5}\2)(.)\3{1}(?!.{0,3}\3)(.)(?!\4{1})(.)\4{1}\5{1}