RegEx Обратные ссылки - PullRequest
       18

RegEx Обратные ссылки

2 голосов
/ 14 января 2010

Имея следующее регулярное выражение:

([a-z])([0-9])\1

Это соответствует a5a, есть ли способ для него также соответствовать a5b, a5c, a5d и так далее?


РЕДАКТИРОВАТЬ: Хорошо, я понимаю, что могу просто использовать ([a-z])([0-9])([a-z]), но у меня очень длинное и сложное регулярное выражение (соответствует sub-sub-sub-sub....- domains или , соответствующий IPv4-адресу ), который действительно выиграл бы от описанного выше поведения. Этого можно достичь с помощью обратных ссылок или чего-то еще?


Анон. ответ - это то, что мне нужно, но оно кажется ошибочным.

Ответы [ 6 ]

3 голосов
/ 14 января 2010

Ответ не с обратными ссылками

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

Tcl:

set exp1 "([a-z])"
regexp "${exp1}([0-9])${exp1}+" $string

Javascript:

var exp1 = '([a-z])';
var regexp = new RegExp(exp1 + '([0-9])' + exp1 + '+');
string.match(regexp);

Perl:

my $exp1 = '([a-z])';
$string =~ /${exp1}([0-9])${exp1}+/;
2 голосов
/ 14 января 2010

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

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

Например, в Ruby:

>> letter = '([a-z])'
=> "([a-z])"
>> /#{letter}([0-9])#{letter}+/ =~ "a5b"
=> 0
>> /#{letter}([0-9])#{letter}+/ =~ "a51"
=> nil

Или в JavaScript:

var letter = '([a-z])';
var re = new RegExp(letter + '([0-9])' + letter + '+');
"a5b".match(re)
2 голосов
/ 14 января 2010

Вам не нужны обратные ссылки, если вторая буква не зависит от первой, верно?

([a-z])([0-9])([a-z])+

EDIT

Если вы просто не хотите повторять последнюю часть снова и снова, тогда:

([a-z])([0-9])([a-z])

Просто убираю '+'.

1 голос
/ 14 января 2010

Я подозреваю, что вы хотите что-то похожее на конструкцию Perl (?PARNO) (это не только для рекурсии;).

/([a-z])([0-9])(?1)+/

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

0 голосов
/ 14 января 2010

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

Возможно, попробуйте Python, который позволяет легко создавать регулярные выражения из небольших блоков. Неясно, разрешено ли вам изменять вашу среду ... вам повезло иметь обратные ссылки.

0 голосов
/ 14 января 2010

Я не слежу за вашим вопросом?

[a-z][0-9][a-z] Exactly 1
[a-z][0-9][a-z]? One or 0
[a-z][0-9][a-z]+ 1 or more
[a-z][0-9][a-z]* 0 or more
...