scala regex replaceAllIn не может заменить, когда строка замены выглядит как регулярное выражение? - PullRequest
8 голосов
/ 12 марта 2012

Я долго работал с Regex replaceAllIn, но столкнулся с проблемой, когда в строке replacement было что-то похожее на регулярное выражение. Следующее иллюстрирует проблему (Scala 2.9.1-1). Обратите внимание, что реальное пространство проблем гораздо сложнее, поэтому идея использования более простого решения на самом деле недопустима (просто чтобы исключить неизбежное «Почему бы вам не попробовать ...»: D)

val data = "val re = \"\"\"^[^/]*://[^/]*/[^/]*$\"\"\".r"
val source = """here
LATEX_THING{abc}
there"""
val re = "LATEX_THING\\{abc\\}".r
println(re.replaceAllIn(source, data))

Это приводит к следующей ошибке:

java.lang.IllegalArgumentException: Illegal group reference

Если я изменю data с того, что было, на что-то простое:

val data = "This will work"

Тогда все хорошо.

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

Чего мне не хватает?

edit : Хорошо, поэтому, посмотрев на класс java.util.regex.Matcher, может показаться, что предполагаемое исправление:

re.replaceAllIn(source, java.util.regex.Matcher.quoteReplacement(data))

1 Ответ

10 голосов
/ 12 марта 2012

Вам нужно экранировать $ в строке замены:

val data = "val re = \"\"\"^[^/]*://[^/]*/[^/]*\\$\"\"\".r"

В противном случае оно интерпретируется как начало групповой ссылки (которая действительна только в том случае, если за $ следуют одна или несколько цифр). См. документацию для java.util.regex.Matcher для более подробной информации:

Строка замены может содержать ссылки на захваченные подпоследовательности во время предыдущего матча: каждое вхождение $g будет заменено на результат оценки group(g) ... Знак доллара ($) может быть включается в качестве литерала в строке замены, предшествуя ему обратная косая черта (\$).

Обновление с учетом вашего комментария и редактирование выше: Да, вы можете использовать Matcher.quoteReplacement, если вы не работаете со строковыми литералами (или, если вы, я думаю, но в этом случае экранирование $ кажется более легким) и, по крайней мере, есть вероятность , что quoteReplacement будет доступен в качестве метода для scala.util.matching.Regex в будущем.

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