Como escaping texto para expressão regular em Java

O Java tem uma maneira interna de escaping de texto arbitrário para que possa ser incluído em uma expressão regular? Por exemplo, se meus usuários digitarem “$ 5”, eu gostaria de corresponder exatamente ao invés de um “5” após o final da input.

Desde o Java 1.5, sim :

Pattern.quote("$5"); 

Diferença entre Pattern.quote e Matcher.quoteReplacement não estava claro para mim antes de ver o seguinte exemplo

 s.replaceFirst(Pattern.quote("text to replace"), Matcher.quoteReplacement("replacement text")); 

Pode ser tarde demais para responder, mas você também pode usar Pattern.LITERAL , que ignoraria todos os caracteres especiais durante a formatação:

 Pattern.compile(textToFormat, Pattern.LITERAL); 

Eu acho que você está atrás de \Q$5\E Veja também Pattern.quote(s) introduzido no Java5.

Veja Pattern javadoc para detalhes.

Primeiro, se

  • você usa replaceAll ()
  • você não usa Matcher.quoteReplacement ()
  • o texto a ser substituído inclui $ 1

Não vai colocar um 1 no final. Ele examinará a regex de pesquisa para o primeiro grupo correspondente e para o subestado THAT. Isso é o que significa US $ 1, US $ 2 ou US $ 3 no texto de substituição: grupos correspondentes do padrão de pesquisa.

Eu freqüentemente conecto longas cadeias de texto em arquivos .properties e, em seguida, gero assuntos e corpos de email deles. Na verdade, essa parece ser a maneira padrão de fazer o i18n no Spring Framework. Eu coloco tags XML, como espaços reservados, nas strings e uso replaceAll () para replace as tags XML pelos valores em tempo de execução.

Eu me deparei com um problema em que um usuário inseria uma cifra de dólares e centavos, com um cifrão. replaceAll () engasgou nele, 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) 

Neste caso, o usuário tinha inserido “$ 3” em algum lugar em sua input e replaceAll () procurava na regex de pesquisa pelo terceiro grupo correspondente, não encontrava um e vomitava.

Dado:

 // "msg" is a string from a .properties file, containing "" among other tags // "userInput" is a String containing the user's input 

substituindo

 msg = msg.replaceAll("", userInput); 

com

 msg = msg.replaceAll("", Matcher.quoteReplacement(userInput)); 

resolveu o problema. O usuário pode colocar em qualquer tipo de caracteres, incluindo cifrões, sem problema. Ele se comportou exatamente do jeito que você esperaria.

Para ter um padrão protegido, você pode replace todos os símbolos por “\\\\”, exceto dígitos e letras. E depois disso você pode colocar em seu padrão protegido seus símbolos especiais para fazer este padrão funcionar não como texto citado, mas realmente como um patten, mas o seu próprio. Sem símbolos especiais do usuário.

 public class Test { public static void main(String[] args) { String str = "yz (111)"; String p1 = "xx (111)"; String p2 = ".* .* \\(111\\)"; p1 = escapeRE(p1); p1 = p1.replace("x", ".*"); System.out.println( p1 + "-->" + str.matches(p1) ); //.*\ .*\ \(111\)-->true System.out.println( p2 + "-->" + str.matches(p2) ); //.* .* \(111\)-->true } public static String escapeRE(String str) { //Pattern escaper = Pattern.compile("([^a-zA-z0-9])"); //return escaper.matcher(str).replaceAll("\\\\$1"); return str.replaceAll("([^a-zA-Z0-9])", "\\\\$1"); } } 

Pattern.quote (“blabla”) funciona bem.

O Pattern.quote () funciona bem. Ele encerra a sentença com os caracteres ” \ Q ” e ” \ E “, e se ele escaping “\ Q” e “\ E”. No entanto, se você precisar fazer uma expressão regular real (ou escape personalizado), você pode usar este código:

 String someText = "Some/s/wText*/,**"; System.out.println(someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0")); 

Este método retorna: Some / \ s / wText * / \, **

Código por exemplo e testes:

 String someText = "Some\\E/s/wText*/,**"; System.out.println("Pattern.quote: "+ Pattern.quote(someText)); System.out.println("Full escape: "+someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0")); 

^ O símbolo (Negation) é usado para corresponder a algo que não está no grupo de caracteres.
Info sobre negação

Expressões regulares