Как точно соответствовать предыдущей группе, включая регистронезависимость - PullRequest
4 голосов
/ 27 мая 2019

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

pattern = r"""
    ([a-zA-Z])    # Match a single letter and capture it as group1
    .*?           # random matches in between
    \1            # Match whatever capture group1 matched
"""

Теперь это соответствует AA, BB и так далее. Пока все хорошо в питоне. Теперь некоторый язык (idk, если движок Python regex делает) позволяет

pattern = r"""
    ([a-zA-Z])    # Match a single letter and capture it as group1
    .*?           # random matches in between
    \U1           # Match group1 in upper case
"""

Есть пара таких «функций», которые позволяют вам несколько манипулировать предыдущими группами захвата, но они очень ограничены по сравнению с тем, что я прочитал на на каком-то сайте regex

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

@re.register_function('X')
def between_x(group):
    return f'X{group}X'

, а затем

pattern = r"""
    ([a-zA-Z]{2})    # Match a single letter and capture it as group1
    .*?              # random matches in between
    (\X1)            # Match if the previous group is inbetween Xes.
"""
# For example, AArandomletterXAAX would match and group1 would be AA
# and second group would be XAAX

Не обязательно быть модулем re, я открыт для любых других движков регулярных выражений.


В качестве примера шаблон должен соответствовать

string: "hello...HELLO"

и не совпадают

string: "hello...hello"

, учитывая, что наша функция

def f(group):
    return group.upper()

1 Ответ

1 голос
/ 28 мая 2019

Этот вопрос довольно интересный, и я уверен, что у него есть отличное решение, если я правильно понимаю.


Мы можем начать с выражения с тремя подвыражениями:

([a-z]+)(.+?)((?=.+[A-Z].+)(?i:\1))

Здесь у нас начальное строчное слово:

([a-z]+)

, за которыми следует что-то среднее:

 (.+?)

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

((?=.+[A-Z].+)(?i:\1))

Мы возвращаемся с флагом i, который работает нормально.

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

Если нет, то на этой группе ((?=.+[A-Z].+) мы можем сосредоточиться пройти нашу желаемую третью группу и провалить нежелательные.

DEMO

...