2012-03-11 11 views
7

Z przyjemnością korzystam z Regexa replaceAllIn przez jakiś czas, ale wystąpił problem, gdy ciąg znaków replacement miał coś, co wyglądało jak regex w nim. Poniższe ilustruje problem (Scala 2.9.1-1). Zauważ, że prawdziwym problemem jest przestrzeń o wiele bardziej skomplikowane, więc pomysł wykorzystania prostsze rozwiązanie jest naprawdę nie do obronienia (tylko uprzedzić nieuniknione „Dlaczego nie spróbujesz ...”: D)scala regex replaceAllIn nie można zastąpić, gdy zastępuje ciąg wygląda jak regex?

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

stanowi to z powodu następującego błędu:

java.lang.IllegalArgumentException: Illegal group reference 

Jeśli zmienię data od tego, co było do czegoś prostego, takich jak:

val data = "This will work" 

Wtedy wszystko jest grzywny.

Wygląda na to, że replaceAllIn szuka jakoś w drugim łańcuchu i używa go jako innego RE do odniesienia się do tego, co zostało zapamiętane z pierwszego RE ... ale doktorzy nic o tym nie mówią.

Czego mi brakuje?

edit: Ok, więc po patrząc na klasę java.util.regex.Matcher, to wydaje się, że przeznaczony jest poprawka:

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

Odpowiedz

9

Musisz uciec $ w swoim łańcuchu zastępującym:

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

W przeciwnym razie jest interpretowany jako początek odwołania do grupy (która byłaby ważna, gdyby po $ następowała jedna lub więcej cyfr). Zobacz the documentation dla java.util.regex.Matcher więcej szczegółów:

The replacement string may contain references to subsequences captured during the previous match: Each occurrence of $g will be replaced by the result of evaluating group(g) ... A dollar sign ($) may be included as a literal in the replacement string by preceding it with a backslash (\$).

aktualizację, aby rozwiązać swój komentarz i edytować powyżej: Tak, można użyć Matcher.quoteReplacement jeśli nie pracujesz z napisowych (lub jeśli są, jak sądzę, ale ucieczki $ wydaje się łatwiejszy w tym przypadku) i jest co najmniej a chance, że quoteReplacement będzie dostępny jako metoda na scala.util.matching.Regex w przyszłości.

+1

Dziękuję, proszę pana. Nie przyszło mi do głowy, aby udać się do dokumentacji w języku Java ... to jest to, co dostaję za to, że nigdy nie byłem prawdziwym koderem Java, jak sądzę. Dane "dane" faktycznie pochodzą z pliku źródłowego Scala. Sądzę, że zasada jest taka, że ​​jeśli nie wiesz dokładnie, co masz, najpierw ją przetwórz, podstawiając '$' for '\ $', a następnie przetwarzaj ją tak, jak chcesz. –