Pergunta

O Java possui uma maneira interna de escapar de texto arbitrário para que possa ser incluído em uma expressão regular?Por exemplo, se meus usuários inserirem "$ 5", gostaria de corresponder exatamente a isso, em vez de "5" após o final da entrada.

Foi útil?

Solução

Desde Java 1.5, sim:

Pattern.quote("$5");

Outras dicas

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, o que ignoraria todos os caracteres especiais durante a formatação:

Pattern.compile(textToFormat, Pattern.LITERAL);

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

Ver Padrão javadoc para obter detalhes.

Em primeiro lugar, 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 para o primeiro grupo correspondente e sub-AQUELE.Isso é o que $1, $2 ou $3 significam no texto de substituição:grupos correspondentes do padrão de pesquisa.

Freqüentemente insiro longas sequências de texto em arquivos .properties e, em seguida, gero assuntos e corpos de e-mail a partir deles.Na verdade, esta parece ser a maneira padrão de fazer i18n no Spring Framework.Coloquei tags XML, como espaços reservados, nas strings e uso replaceAll() para substituir as tags XML pelos valores em tempo de execução.

Encontrei um problema em que um usuário inseria um valor em dólares e centavos, com um cifrão.replaceAll() engasgou com isso, 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 inseriu "$3" em algum lugar em sua entrada e replaceAll() procurou no regex de pesquisa o terceiro grupo correspondente, não encontrou nenhum 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 poderia inserir qualquer tipo de caractere, incluindo cifrões, sem problemas.Ele se comportou exatamente da maneira que você esperaria.

Para ter um padrão protegido você pode substituir todos os símbolos por "\\\\", exceto dígitos e letras.E depois disso você pode colocar naquele padrão protegido seus símbolos especiais para fazer esse padrão funcionar não como um texto citado estúpido, mas realmente como um padrão, mas seu próprio.Sem símbolos especiais do usuário.

public class Test {
    public static void main(String[] args) {
        String str = "y z (111)";
        String p1 = "x x (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.Inclui a frase com os caracteres "\Q" e "\E", e se escapar de "\Q" e "\E".No entanto, se você precisar fazer um escape de expressão regular real (ou escape personalizado), poderá usar este código:

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

Este método retorna: Alguns/\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 ^ (negação) é usado para corresponder a algo que não está no grupo de caracteres.

Este é o link para Expressões regulares

Aqui estão as informações da imagem sobre a negação:

Info about negation

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top