Прямая ссылка в регулярном выражении

В чем разница следующих регулярных выражений?

(\2amigo|(go!))+
(amigo|(go!))+

Они оба соответствуют одним и тем же строкам. https://regexr.com/3u62t

Как работает прямая ссылка?


person kame    schedule 20.08.2018    source источник
comment
В ECMAScript каждая обратная ссылка предварительно инициализируется пустой строкой. В PCRE он не будет соответствовать одним и тем же строкам.   -  person Wiktor Stribiżew    schedule 20.08.2018
comment
Пожалуйста, обновите вопрос, указав, что вы ожидаете от шаблона из предоставленных строк.   -  person Wiktor Stribiżew    schedule 20.08.2018


Ответы (3)


На самом деле это вообще не работает (хотя, как заметил Виктор Стрибижев, это могло бы быть с другими вариантами регулярных выражений).

Когда \n относится к группе захвата, которая ничего не захватила, это соответствует пустой строке. Вы можете увидеть это, например. /(a)?b\1/, что соответствует b.

Когда \n относится к группе захвата, которая появляется позже в шаблоне, обычно она еще ничего не захватила. Вы можете увидеть это, например. /\1b(a)/, что соответствует ba.

Вы можете подумать, что при повторении предыдущие захваты сохраняются, так что /(\2a(b))*/ соответствует abbab, но это не так: при повторении, когда начинается новое совпадение, захваты сбрасываются. Вместо этого он соответствует abab, не abbab.

В результате прямая ссылка полностью и совершенно бесполезна и соответствует только пустой строке. Между двумя вашими шаблонами нет никакой разницы.

person Community    schedule 20.08.2018
comment
@WiktorStribiżew Я имел в виду, что на самом деле это вообще не работает в качестве прямой ссылки. Он никогда не ссылается ни на что, что было захвачено. - person ; 20.08.2018
comment
@kame Это начинается с ПРИМЕЧАНИЕ. Прямая ссылка поддерживается вариантами регулярных выражений JGsoft, .NET, Java, Perl, PCRE, PHP, Delphi и Ruby. -- JavaScript не указан, и это правильно. Вы уверены, что хотите спросить о JavaScript? - person ; 20.08.2018
comment
@kame Пожалуйста, будьте осторожны при редактировании своего вопроса, чтобы сделать это таким образом, чтобы он не аннулировал полностью существующие ответы. В этом случае простое изменение тегов в любом случае было бы неуместным, поскольку вы все еще используете пример JavaScript, который не демонстрирует, что вы намеревались отредактировать вопрос, чтобы вместо этого задать. Во всяком случае, для .NET вы можете подумать, что часть ... на самом деле истинна (и она соответствует пустой строке, ложна); это должно сказать вам, как это работает. - person ; 20.08.2018
comment
Что мне теперь делать? - person kame; 21.08.2018
comment
@kame Я не совсем уверен. Один из вариантов — изменить свой вопрос, чтобы спросить только о JavaScript, и, при желании, задать новый вопрос о .NET (убедившись, что вы используете онлайн-демонстрацию, в которой используются регулярные выражения .NET), если вы все еще ищете более подробную информацию об этом. Возможно, есть лучший вариант, которого я не вижу. - person ; 21.08.2018

Второй "(amigo|(go!))+" захватывает: amigoamigo

Первый "(\2amigo|(вперед!))+ " не работает.

person Khaled Zoheir    schedule 07.04.2020

Поведение зависит от языка.

В Ruby и Perl также можно использовать прямые ссылки, но убедитесь, что ссылочная скобка совпала, когда она будет использоваться. Обычно это означает, что прямая ссылка находится внутри некоторой группы повторов. Например, в Ruby это регулярное выражение совпадает с train только в том случае, если перед ним стоит хотя бы один префикс choo:

$ irb
irb(main):052:0> regex = /(\2train|(choo))+/
=> /(\2train|(choo))+/
irb(main):053:0> 'choochootrain' =~ regex
=> 0
irb(main):054:0> $&
=> "choochootrain"
irb(main):055:0> $1
=> "chootrain"
irb(main):056:0> $2
=> "choo"
irb(main):004:0> 'train' =~ regex
=> nil

В JavaScript это не так:

[~/.../github-actions/225-github-actions-demo(master)]$ node
Welcome to Node.js v13.5.0.
Type ".help" for more information.
> regex = /(\2train|(choo))+/
/(\2train|(choo))+/
> regex.exec('train')
[
  'train',
  'train',
  undefined,
  index: 0,
  input: 'train',
  groups: undefined
]

На самом деле он соответствует train (предполагается, что \2 пусто):

person Casiano    schedule 24.03.2021