Lijst met alle speciale tekens die in een regex moeten worden geëscaped

Ik probeer een toepassing te maken die overeenkomt met een berichtsjabloon met een bericht dat een gebruiker probeert te verzenden. Ik gebruik Java-regex om het bericht te matchen. De sjabloon/het bericht kan speciale tekens bevatten.

Hoe krijg ik de volledige lijst met speciale tekens die moeten worden escaped om mijn regex te laten werken en in de grootst mogelijke gevallen overeen te laten komen?

Is er een universele oplossing voor het escapen van alle speciale tekens in Java-regex?


Antwoord 1, autoriteit 100%

Je kunt de javadoc van de klasse Pattern bekijken: http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html

Je moet elk teken dat daar wordt vermeld escapen als je het gewone teken wilt en niet de speciale betekenis.

Als een misschien eenvoudigere oplossing, kunt u de sjabloon tussen \Q en \E plaatsen – alles daartussen wordt als escaped beschouwd.


Antwoord 2, autoriteit 93%

  • Java-tekens die in reguliere expressies als escapeteken moeten worden gebruikt, zijn:
    \.[]{}()<>*+-=!?^$|
  • Twee van de afsluitende haakjes (]en }) hoeven alleen te worden escaped na het openen van hetzelfde type haakje.
  • Tussen []-haakjes werken sommige tekens (zoals +en -) soms zonder escape.

Antwoord 3, autoriteit 31%

Om te ontsnappen kun je dit gewoon gebruiken van Java 1.5:

Pattern.quote("$test");

U komt exact overeen met het woord $test


Antwoord 4, autoriteit 18%

Volgens de String Literals / Metacharactersdocumentatiepagina, ze zijn:

<([{\^-=$!|]})?*+.>

Het zou ook gaaf zijn om die lijst ergens in code te laten verwijzen, maar ik weet niet waar dat zou kunnen zijn…


Antwoord 5, autoriteit 7%

In combinatie met wat iedereen zei, stel ik het volgende voor, om de lijst met karakters die speciaal zijn voor RegExp duidelijk in hun eigen String te houden, en om te voorkomen dat je moet proberen duizenden “\\”‘s visueel te ontleden. Dit lijkt redelijk goed te werken voor mij:

final String regExSpecialChars = "<([{\\^-=$!|]})?*+.>";
final String regExSpecialCharsRE = regExSpecialChars.replaceAll( ".", "\\\\$0");
final Pattern reCharsREP = Pattern.compile( "[" + regExSpecialCharsRE + "]");
String quoteRegExSpecialChars( String s)
{
    Matcher m = reCharsREP.matcher( s);
    return m.replaceAll( "\\\\$0");
}

Antwoord 6, autoriteit 5%

Op suggestie van @Sorin van de Java Pattern-documenten, lijkt het erop dat tekens om te ontsnappen ten minste zijn:

\.[{(*+?^$|

Antwoord 7, autoriteit 4%

De Pattern.quote(String s)doet ongeveer wat je wilt. Het laat echter een beetje te wensen over; het ontsnapt niet echt aan de individuele karakters, maar omhult de string gewoon met \Q...\E.

Er is geen methode die precies doet wat u zoekt, maar het goede nieuws is dat het eigenlijk vrij eenvoudig is om te ontsnappen aan alle speciale tekens in een reguliere Java-expressie:

regex.replaceAll("[\\W]", "\\\\$0")

Waarom werkt dit? Welnu, de documentatie voor Patternzegt specifiek dat het is toegestaan om te ontsnappen aan niet-alfabetische tekens die niet per se moeten worden ontsnapt:

Het is een fout om een backslash te gebruiken voorafgaand aan een alfabetisch teken dat geen escaped construct aangeeft; deze zijn gereserveerd voor toekomstige uitbreidingen van de reguliere expressietaal. Een backslash mag worden gebruikt vóór een niet-alfabetisch teken, ongeacht of dat teken deel uitmaakt van een constructie zonder escapetekens.

Bijvoorbeeld ;is geen speciaal teken in een reguliere expressie. Als je er echter aan ontsnapt, zal Pattern\;nog steeds interpreteren als ;. Hier zijn nog een paar voorbeelden:

  • >wordt \>wat gelijk is aan >
  • [wordt \[wat de escape-vorm is van [
  • 8is nog steeds 8.
  • \)wordt \\\)wat de escape-vorm is van \en (aaneengeschakeld.

Opmerking:de sleutel is de definitie van “niet-alfabetisch”, wat in de documentatie in feite “niet-woord” tekens betekent, of tekens buiten het teken stel [a-zA-Z_0-9]in.


Antwoord 8, autoriteit 4%

hoewel het antwoord voor Java is, maar de code kan eenvoudig worden aangepast vanuit deze Kotlin String-extensie die ik heb bedacht (aangepast van de door @brcolow verstrekte):

private val escapeChars = charArrayOf(
    '<',
    '(',
    '[',
    '{',
    '\\',
    '^',
    '-',
    '=',
    '$',
    '!',
    '|',
    ']',
    '}',
    ')',
    '?',
    '*',
    '+',
    '.',
    '>'
)
fun String.escapePattern(): String {
    return this.fold("") {
      acc, chr ->
        acc + if (escapeChars.contains(chr)) "\\$chr" else "$chr"
    }
}
fun main() {
    println("(.*)".escapePattern())
}

print \(\.\*\)

check het hier in actie https://pl.kotl.in/h-3mXZkNE


Antwoord 9, autoriteit 3%

aan de andere kant van de medaille moet u een “non-char”-regex gebruiken die er zo uitziet als speciale tekens = allChars – number – ABC – spatie in uw app-context.

String regepx = "[^\\s\\w]*";

Antwoord 10

Ervan uitgaande dat u de lijst met escape-tekens die Java regex gebruikt hebt en vertrouwt (om gezaghebbend te zijn) (zou leuk zijn als deze tekens in een of ander lid van de Pattern-klasse zichtbaar zijn), kunt u de volgende methode gebruiken om aan het teken te ontsnappen als dat zo is inderdaad nodig:

private static final char[] escapeChars = { '<', '(', '[', '{', '\\', '^', '-', '=', '$', '!', '|', ']', '}', ')', '?', '*', '+', '.', '>' };
private static String regexEscape(char character) {
    for (char escapeChar : escapeChars) {
        if (character == escapeChar) {
            return "\\" + character;
        }
    }
    return String.valueOf(character);
}

Other episodes