2012-03-11 15 views
7

Sono stato felicemente in esecuzione un Regex replaceAllIn per un po 'di tempo ma si è verificato un problema quando la stringa replacement aveva qualcosa che sembrava una regex in esso. Quanto segue illustra il problema (Scala 2.9.1-1). Si noti che il vero e proprio spazio problema è molto più complesso, per cui l'idea di utilizzare una soluzione più semplice in realtà non è plausibile (solo per prevenire l'inevitabile: "Perché non provi ...": D)scala regex replaceAllIn non può sostituire quando la stringa di sostituzione sembra una regex?

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

Questo presenta con il seguente errore:

java.lang.IllegalArgumentException: Illegal group reference 

Se cambio data da quello che era per qualcosa di semplice come:

val data = "This will work" 

Allora va tutto bene.

Sembra che replaceAllIn stia cercando in qualche modo nella seconda stringa e utilizzandolo come un altro RE per fare riferimento a ciò che è stato ricordato dal primo RE ... ma i documenti non dicono nulla al riguardo.

Cosa mi manca?

modificare: Ok, così dopo aver guardato la classe java.util.regex.Matcher, sembrerebbe che la correzione previsto è:

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

risposta

9

avete bisogno di sfuggire alla $ nella stringa di sostituzione:

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

Altrimenti è interpretato come l'inizio di un riferimento di gruppo (che sarebbe valido solo se lo $ fosse seguito da una o più cifre). Vedere the documentation per java.util.regex.Matcher per maggiori dettagli:

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 (\$).

aggiornamento per risolvere il tuo commento e modificare sopra: Sì, è possibile utilizzare Matcher.quoteReplacement se non stai lavorando con le stringhe (o se si è, credo, ma in fuga il $ sembra più facile in questo caso) e c'è almeno a chance che quoteReplacement sarà disponibile come metodo su scala.util.matching.Regex in futuro.

+1

Grazie signore. Non mi è venuto in mente di andare ai documenti Java ... è quello che ottengo per non essere mai stato un vero programmatore Java, immagino. I 'dati' in questione provengono in realtà da un file sorgente Scala. Immagino che la regola empirica sia, a meno che tu non sappia esattamente quello che hai, preprimalo prima sostituendo il '$' per '\ $' e poi elaboralo nel modo che desideri. –