Проведя некоторое исследование, я понял проблемы: Perl имел , чтобы использовать другой символ для обратных ссылок на шаблоны и обратных ссылок, а java.util.regex.*
не имеет следовать примеру, по своему усмотрению, не по технической, а по традиционной причине.
На стороне Perl
(Пожалуйста, имейте в виду, что все, что я знаю о Perl на данный момент, получено из чтения статей Википедии, так что не стесняйтесь исправлять любые ошибки, которые я мог сделать)
Причина, по которой пришлось сделать 1011 * таким образом в Perl, заключается в следующем:
- Perl использует
$
в качестве сигилы (то есть символ, прикрепленный к имени переменной).
- Строковые литералы Perl интерполируются переменными.
- Регулярное выражение Perl фактически захватывает группы как переменные
$1
, $2
и т. Д.
Таким образом, из-за того, как Perl интерпретируется и как работает его механизм регулярных выражений, должен использоваться предшествующий слеш для обратных ссылок (например, \1
) в шаблоне, потому что если вместо него используется символ $
(например, $1
), это приведет к непреднамеренной интерполяции переменных в шаблон.
Строка замены, из-за того, как она работает в Perl, оценивается в контексте каждого совпадения. Для Perl наиболее естественно использовать здесь интерполяцию переменных, поэтому механизм регулярных выражений собирает группы в переменные $1
, $2
и т. Д., Чтобы это работало без проблем с остальным языком.
Ссылки
На стороне Java
Java - это совсем другой язык, чем Perl, но самое важное здесь то, что здесь нет интерполяции переменных. Более того, replaceAll
является вызовом метода, и, как и при всех вызовах методов в Java, аргументы оцениваются один раз, до вызова метода.
Таким образом, одной лишь функции интерполяции переменных недостаточно, поскольку по сути строка замены должна переоцениваться при каждом совпадении, и это просто не семантика вызовов методов в Java. Переменная с интерполяцией, которая вычисляется до , даже когда вызывается * 1059, практически бесполезна; интерполяция должна происходить во время метода, при каждом совпадении.
Поскольку это не семантика языка Java, replaceAll
должен выполнить эту «своевременную» интерполяцию вручную . Таким образом, абсолютно никаких технических причин , почему $
является escape-символом для обратных ссылок в замещающих строках. Это вполне могло быть \
. И наоборот, обратные ссылки в шаблоне также можно было бы экранировать с помощью $
вместо \
, и технически все равно работало бы так же хорошо.
Причина, по которой Java выполняет регулярные выражения, является чисто традиционной: она просто следует прецеденту, установленному Perl.