Primeiro, se
- você usa replaceAll ()
- você NÃO usa Matcher.quoteReplacement ()
- o texto a ser substituído inclui $ 1
não colocará 1 no final. Ele examinará o regex de pesquisa do primeiro grupo e sub-grupo correspondente. É isso que $ 1, $ 2 ou $ 3 significa no texto de substituição: grupos correspondentes do padrão de pesquisa.
Freqüentemente, plugue longas seqüências de texto em arquivos .properties e depois gero assuntos e corpos de email a partir deles. De fato, essa parece ser a maneira padrão de executar o i18n no Spring Framework. Coloco marcas XML, como espaços reservados, nas seqüências de caracteres e uso replaceAll () para substituir as marcas XML pelos valores em tempo de execução.
Encontrei um problema em que um usuário inseria uma figura de dólares e centavos, com um cifrão. replaceAll () engasgou, com o seguinte aparecendo em um stracktrace:
java.lang.IndexOutOfBoundsException: No group 3
at java.util.regex.Matcher.start(Matcher.java:374)
at java.util.regex.Matcher.appendReplacement(Matcher.java:748)
at java.util.regex.Matcher.replaceAll(Matcher.java:823)
at java.lang.String.replaceAll(String.java:2201)
Nesse caso, o usuário digitou "$ 3" em algum lugar da entrada e replaceAll () foi procurar no regex de pesquisa o terceiro grupo correspondente, não encontrou um e vomitou.
Dado:
// "msg" is a string from a .properties file, containing "<userInput />" among other tags
// "userInput" is a String containing the user's input
substituindo
msg = msg.replaceAll("<userInput \\/>", userInput);
com
msg = msg.replaceAll("<userInput \\/>", Matcher.quoteReplacement(userInput));
resolveu o problema. O usuário pode inserir qualquer tipo de caractere, incluindo cifrões, sem problemas. Ele se comportou exatamente da maneira que você esperaria.
\Q
e\E
. Isso pode levar a resultados inesperados, por exemploPattern.quote("*.wav").replaceAll("*",".*")
, resultará\Q.*.wav\E
e não.*\.wav
, conforme o esperado."mouse".toUpperCase().replaceAll("OUS","ic")
isso retornaráMicE
. Você would't esperar que voltarMICE
porque você não se aplicavatoUpperCase()
noic
. No meu exemploquote()
é aplicado no.*
insertetreplaceAll()
também. Você tem que fazer outra coisa, talvez.replaceAll("*","\\E.*\\Q")
funcione, mas isso é contra-intuitivo.*.wav
o padrão regex\*\.wav
e o replaceAll o transformaria\.*\.wav
, o que significa que seria corresponde aos arquivos cujo nome consiste em um número arbitrário de períodos seguidos por.wav
. Você provavelmente precisariareplaceAll("\\*", ".*")
se eles tivessem adotado a implementação mais frágil que depende do reconhecimento de todos os possíveis caracteres regex ativos e escapando deles individualmente ... isso seria muito mais fácil?