Соответствие повторяющимся подстрокам в регулярном выражении - PullRequest
24 голосов
/ 30 мая 2009

Возможно ли совпадение регулярного выражения на основе других частей того же регулярного выражения?

Например, как бы сопоставить строки, начинающиеся и заканчивающиеся одинаковой последовательностью из 3 символов, независимо от того, что это за символы?

Матчи:

abcabc
xyz abc xyz

Не соответствует:

abc123

Не определено: (Может совпадать или нет, в зависимости от того, что проще)

ababa
a

В идеале, я бы хотел что-то в духе Perl Regex. Если это невозможно, мне было бы интересно узнать, есть ли варианты, которые может сделать.

Ответы [ 4 ]

27 голосов
/ 30 мая 2009

Использовать группы захвата и обратные ссылки.

/^(.{3}).*\1$/

\1 относится к тому, что соответствует содержимому первой группы захвата (содержимому ()). Регулярные выражения в большинстве языков допускают нечто подобное.

16 голосов
/ 30 мая 2009

Вам нужно обратных ссылок . Идея состоит в том, чтобы использовать группу захвата для первого бита, а затем обращаться к ней, когда вы пытаетесь сопоставить последний бит. Вот пример сопоставления пары начальных и конечных тегов HTML (по приведенной ранее ссылке):

<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1>

Это регулярное выражение содержит только одну пару круглых скобок, которые записывают строку, совпадающую с [A-Z][A-Z0-9]*, в первую обратную ссылку. Эта обратная ссылка повторно используется с \1 (с обратной косой чертой). / перед этим - просто косая черта в закрывающем HTML-теге, которому мы пытаемся соответствовать.

Применение этого к вашему делу:

/^(.{3}).*\1$/

(Да, это регулярное выражение, опубликованное Брайаном Карпером. Просто не так много способов сделать это.)

Подробное объяснение ради потомков (не обижайтесь, если оно под вами):

  • ^ соответствует началу строки.
  • (.{3}) получает три символа любого типа и сохраняет их в группе для дальнейшего использования.
  • .* соответствует чему угодно как можно дольше. (Вам не важно, что находится в середине строки.)
  • \1 соответствует группе, которая была захвачена на шаге 2.
  • $ соответствует концу строки.
3 голосов
/ 30 мая 2009

Для одинаковых символов в начале и конце:

/^(.{3}).*\1$/

Это обратная ссылка .

2 голосов
/ 30 мая 2009

Это работает:

my $test = 'abcabc';
print $test =~ m/^([a-z]{3}).*(\1)$/;

Для соответствия начала и конца вы должны добавить ^ и $ якоря.

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