Vejledning til at undslippe tegn i Java RegExps

1. Oversigt

Regulære udtryk API i Java, java.util.regex bruges i vid udstrækning til mønstermatchning For at finde ud af mere kan du følge denne artikel.

I denne artikel vil vi fokusere på at undslippe tegn med et regulært udtryk og vise, hvordan det kan gøres i Java.

2. Særlige RegExp-tegn

I henhold til Java-dokumentationen til Java-regulære udtryk er der et sæt specialtegn, også kendt som metategn, der findes i et regulært udtryk.

Når vi vil tillade tegnene, som de er, i stedet for at fortolke dem med deres særlige betydning, er vi nødt til at undslippe dem. Ved at undslippe disse tegn tvinger vi dem til at blive behandlet som almindelige tegn, når vi matcher en streng med et givet regulært udtryk.

De metategn, som vi normalt har brug for for at flygte på denne måde, er:

Lad os se på et simpelt kodeeksempel, hvor vi matcher et input Snor med et mønster udtrykt i et regulært udtryk.

Denne test viser, at for en given inputstreng foof når mønsteret foo. (foo slutter med et priktegn) matches, returnerer den en værdi på rigtigt hvilket indikerer, at kampen er vellykket.

@Test offentlig ugyldighed givenRegexWithDot_whenMatchingStr_thenMatches () {String strInput = "foof"; Streng strRegex = "foo."; assertEquals (true, strInput.matches (strRegex)); }

Du undrer dig måske over, hvorfor er kampen vellykket, når der ikke er nogen prik (.) Tegn til stede i input Snor?

Svaret er simpelt. Prikken (.) Er en metakarakter - punktets særlige betydning her er, at der kan være 'ethvert tegn' i stedet for. Derfor er det klart, hvordan matcheren bestemte, at et match blev fundet.

Lad os sige, at vi ikke ønsker at behandle punktet (.) Med sin unikke betydning. I stedet ønsker vi, at det fortolkes som et punkttegn. Dette betyder, at vi i det foregående eksempel ikke ønsker at lade mønsteret foo. at have et match i input Snor.

Hvordan ville vi håndtere en situation som denne? Svaret er: vi er nødt til at undslippe priktegnet (.), så dets særlige betydning bliver ignoreret.

Lad os grave nærmere ind i det i næste afsnit.

3. Undslippe tegn

Ifølge Java API-dokumentationen til regulære udtryk er der to måder, hvorpå vi kan undslippe tegn, der har særlig betydning. Med andre ord at tvinge dem til at blive behandlet som almindelige tegn.

Lad os se, hvad de er:

  1. Forud for en metakarakter med en tilbageslag (\)
  2. Vedlæg en metategn med \ Q og \ E

Dette betyder bare, at hvis vi i det eksempel, vi så tidligere, ønsker at undslippe punkttegnet, skal vi sætte et tilbageslagstegn foran punkttegnet. Alternativt kan vi placere priktegnet mellem \ Q og \ E.

3.1. Undslipper ved hjælp af tilbageslag

Dette er en af ​​de teknikker, som vi kan bruge til at undslippe metategn i et regulært udtryk. Vi ved dog, at backslash-tegnet er et escape-tegn i Java Snor også bogstaver. Derfor er vi nødt til at fordoble tilbageslagstegnet, når vi bruger det forud for ethvert tegn (inklusive selve \ tegnet).

Derfor er vi i vores eksempel nødt til at ændre det regulære udtryk som vist i denne test:

@Test offentlig ugyldighed givenRegexWithDotEsc_whenMatchingStr_thenNotMatching () {String strInput = "foof"; Streng strRegex = "foo \."; assertEquals (false, strInput.matches (strRegex)); }

Her er punkttegnet undsluppet, så matcheren behandler det simpelthen som en prik og forsøger at finde et mønster, der ender med prikken (dvs. foo.).

I dette tilfælde vender det tilbage falsk da der ikke er noget match i input Snor til det mønster.

3.2. Undslipper ved hjælp af \ Q & \ E

Alternativt kan vi bruge \ Q og \ E for at undslippe den særlige karakter. \ Q angiver, at alle tegn op til \ E skal undslippes og \ E betyder, at vi er nødt til at afslutte den flugt, der blev startet med \ Q.

Dette betyder bare, at hvad der er imellem \ Q og \ E ville være undsluppet.

I den test, der er vist her, er dele() af Snor klasse laver en kamp ved hjælp af det regulære udtryk, der gives til den.

Vores krav er at opdele inputstrengen af ​​pipetegnet (|) i ord. Derfor bruger vi et regulært udtryksmønster til at gøre det.

Rørkarakteren er en metakarakter, der skal undslippes i det regulære udtryk.

Her sker flugt ved at placere rørkarakteren imellem \ Q og \ E:

@Test offentligt ugyldigt givetRegexWithPipeEscaped_whenSplitStr_thenSplits () \ E "; assertEquals (4, strInput.split (strRegex) .length); 

4. Den Mønster. Citat (streng S) Metode

Mønsteret.Citat (streng S) -metoden i java.util.regex.Mønster klasse konverterer et givet mønster for regulært udtryk Snor ind i et bogstaveligt mønster Snor. Dette betyder, at alle metategn i input Snor behandles som almindelige tegn.

Brug af denne metode ville være et mere praktisk alternativ end at bruge \ Q & \ E som det indpakker det givne Snor med dem.

Lad os se denne metode i aktion:

@Test offentligt ugyldigt givetRegexWithPipeEscQuoteMeth_whenSplitStr_thenSplits () bar

I denne hurtige test blev den Pattern.quote () metoden bruges til at undslippe det givne regex-mønster og omdanne det til et Snor bogstavelig. Med andre ord undgår det alle de metategn, der findes i regex-mønsteret for os. Det gør et lignende job som \ Q & \ E.

Røret karakter er undsluppet af Pattern.quote () metode og dele() fortolker det som en Snor bogstavelig, hvormed den deler input.

Som vi kan se, er dette en meget renere tilgang, og også udviklerne behøver ikke at huske alle flugtsekvenserne.

Det skal vi bemærke Mønster. Citat omslutter hele blokken med en enkelt escape-sekvens. Hvis vi ønskede at undslippe tegn individuelt, skulle vi bruge en token-udskiftningsalgoritme.

5. Yderligere eksempler

Lad os se på, hvordan erstatteAlle () metode til java.util.regex.Matcher arbejder.

Hvis vi har brug for at erstatte alle forekomster af en given karakter Snor med en anden kan vi bruge denne metode ved at videregive et regulært udtryk til den.

Forestil dig, at vi har et input med flere forekomster af $ Karakter. Det resultat, vi ønsker at få, er den samme streng med $ karakter erstattet af £.

Denne test viser, hvordan mønsteret $ passeres uden at være undsluppet:

@Test offentligt ugyldigt givenRegexWithDollar_whenReplacing_thenNotReplace () {String strInput = "Jeg gav $ 50 til min bror." + "Han købte slik til $ 35. Nu har han $ 15 tilbage."; Streng strRegex = "$"; Streng strReplacement = "£"; String output = "Jeg gav £ 50 til min bror." + "Han købte slik til £ 35. Nu har han £ 15 tilbage."; Mønster p = Mønster.kompil (strRegex); Matcher m = s. Matcher (strInput); assertThat (output, ikke (equalTo (m.replaceAll (strReplacement)))); }

Testen hævder det $ erstattes ikke korrekt af £.

Nu hvis vi undgår regex-mønsteret, sker udskiftningen korrekt, og testen passerer som vist i dette kodestykke:

@Test offentlig ugyldighed givenRegexWithDollarEsc_whenReplacing_thenRplace () {String strInput = "Jeg gav $ 50 til min bror." + "Han købte slik til $ 35. Nu har han $ 15 tilbage."; Streng strRegex = "\ $"; Streng strReplacement = "£"; String output = "Jeg gav £ 50 til min bror." + "Han købte slik til £ 35. Nu har han £ 15 tilbage."; Mønster p = Pattern.compile (strRegex); Matcher m = s. Matcher (strInput); assertEquals (output, m.replaceAll (strReplacement)); }

Bemærk \\$ her, hvilket gør tricket ved at flygte fra $ karakter og matchende mønster.

6. Konklusion

I denne artikel kiggede vi på undslippe tegn i regulære udtryk i Java.

Vi diskuterede, hvorfor regelmæssige udtryk skal undslippes, og de forskellige måder, hvorpå det kan opnås.

Som altid kan kildekoden relateret til denne artikel findes på GitHub.