Как сопоставить четное число любого символа в строке? - PullRequest
2 голосов
/ 16 марта 2019

У меня есть строка:

aaabbashasccddee

И я хочу получить совпадения четного числа последовательных одинаковых символов. Например, из приведенной выше строки я хочу эти совпадения:

[bb],[cc],[dd],[ee]

Я пробовал это решение, но оно даже не близко:

"^(..)*$

Любая помощь, пожалуйста

Ответы [ 2 ]

5 голосов
/ 16 марта 2019

К счастью, регулярные выражения .NET способны обрабатывать бесконечные объекты.То, что вам нужно, может быть достигнуто с помощью следующего регулярного выражения:

((?>(?(2)(?=\2))(.)\2)+)(?<!\2\1)(?!\2)

См. живую демонстрацию здесь

Распределение регулярных выражений:

  • ( Начало группы захвата # 1
    • (?> Начало группы без захвата (атомарный)
      • (?(2) Если установлена ​​группа захвата # 2
        • (?=\2) Следующим символом должен быть
      • ) Конец f условно
      • (.)\2 Совпадение и захват символа и сопоставление его снова (четное число)
    • )+ Повторять как можно больше, по крайней мере, один раз
  • ) Конец группы захвата # 1
  • (?<!\2\1) Вот трюк.Взгляд назад сообщает движку, что непосредственно предшествующий символ, который предшествует тому, что мы до сих пор сопоставляли, не должен быть тем же самым символом, хранящимся в группе захвата # 2
  • (?!\2) Следующий символ не должен совпадать ссимвол хранится в группе захвата # 2

ОБНОВЛЕНИЕ:

Таким образом, вы можете выполнить следующий код в C #, чтобы получить все четные последовательности символов в строке на Regexбез каких-либо других операторов (чистый Regex).

var allEvenSequences = Regex.Matches("aaabbashasccddee", @"((?>(?(2)(?=\2))(.)\2)+)(?<!\2\1)(?!\2)").Cast<Match>().ToList();

Также, если вы хотите сделать [bb],[cc],[dd],[ee], вы можете присоединиться к этому массиву последовательностей:

string strEvenSequences = string.Join(",", allEvenSequence.Select(x => $"[{x}]").ToArray());
//strEvenSequences will be [bb],[cc],[dd],[ee]
2 голосов
/ 16 марта 2019

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

(.)(?<!\1\1)\1(?:\1\1)*(?!\1)

Разбивка:

(.)         # First capturing group - matches any character.
(?<!\1\1)   # Negative lookbehind - ensures the matched char isn't preceded by the same char.
\1          # Match another one of the character in the 1st group (at least two in total).
(?:\1\1)    # A non-capturing group that matches two occurrences of the same char.
*           # Matches between zero and unlimited times of the previous group.
(?!\1)      # Negative lookahead to make sure no extra occurrence of the char follows.

Демо-версия:

string input = "aaabbashasccddee";
string pattern = @"(.)(?<!\1\1)\1(?:\1\1)*(?!\1)";
var matches = Regex.Matches(input, pattern);
foreach (Match m in matches)
    Console.WriteLine(m.Value);

Выход:

bb
cc
dd
ee

Попробуйте онлайн .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...