Gids voor ontsnappende tekens in Java RegExps

1. Overzicht

De reguliere expressies API in Java, java.util.regex wordt veel gebruikt voor het matchen van patronen. Volg dit artikel om meer te ontdekken.

In dit artikel zullen we ons concentreren op het ontsnappen van tekens binnen een reguliere expressie en laten we zien hoe dit in Java kan worden gedaan.

2. Speciale RegExp-tekens

Volgens de Java-documentatie voor reguliere expressies is er een set speciale tekens die ook wel metatekens worden genoemd in een reguliere expressie.

Als we de karakters willen toestaan ​​zoals ze zijn in plaats van ze te interpreteren met hun speciale betekenissen, moeten we eraan ontsnappen. Door aan deze tekens te ontsnappen, dwingen we ze om als gewone tekens te worden behandeld bij het matchen van een string met een bepaalde reguliere expressie.

De metatekens die we gewoonlijk op deze manier moeten ontsnappen, zijn:

Laten we eens kijken naar een eenvoudig codevoorbeeld waarin we een invoer matchen Draad met een patroon uitgedrukt in een reguliere expressie.

Deze test laat zien dat voor een gegeven invoerstring foof wanneer het patroon foo. (foo eindigend met een punt-teken) overeenkomt, retourneert het de waarde waar wat aangeeft dat de match succesvol is.

@Test openbare ongeldig gegevenRegexWithDot_whenMatchingStr_thenMatches () {String strInput = "foof"; String strRegex = "foo."; assertEquals (true, strInput.matches (strRegex)); }

Je vraagt ​​je misschien af ​​waarom de match succesvol is als er geen punt (.) Teken aanwezig is in de invoer Draad?

Het antwoord is simpel. De punt (.) Is een metateken - de speciale betekenis van punt hier is dat er ‘elk teken 'op zijn plaats kan staan. Daarom is het duidelijk hoe de matcher heeft vastgesteld dat er een match is gevonden.

Laten we zeggen dat we het puntteken (.) Niet willen behandelen met zijn unieke betekenis. In plaats daarvan willen we dat het wordt geïnterpreteerd als een puntteken. Dit betekent dat we in het vorige voorbeeld het patroon niet willen laten foo. om een ​​match in de input te hebben Draad.

Hoe zouden we een dergelijke situatie aanpakken? Het antwoord is: we moeten ontsnappen aan het punt (.) - teken zodat de speciale betekenis ervan wordt genegeerd.

Laten we er in de volgende sectie meer in detail op ingaan.

3. Ontsnappende karakters

Volgens de Java API-documentatie voor reguliere expressies zijn er twee manieren waarop we tekens met een speciale betekenis kunnen escapen. Met andere woorden, om ze te dwingen als gewone karakters te worden behandeld.

Laten we eens kijken wat ze zijn:

  1. Laat een metateken voorafgaan door een backslash (\)
  2. Omsluit een metateken met \ Q en \ E

Dit betekent alleen dat in het voorbeeld dat we eerder zagen, als we willen ontsnappen aan het punt-teken, we een backslash-teken voor het punt-teken moeten plaatsen. Als alternatief kunnen we het puntteken tussen \ Q en \ E plaatsen.

3.1. Ontsnappen met behulp van Backslash

Dit is een van de technieken die we kunnen gebruiken om metatekens in een reguliere expressie te ontsnappen. We weten echter dat het backslash-teken een escape-teken is in Java Draad letterlijke ook. Daarom moeten we het backslash-teken verdubbelen als het wordt gebruikt om aan een willekeurig teken vooraf te gaan (inclusief het teken \ zelf).

Daarom moeten we in ons voorbeeld de reguliere expressie wijzigen zoals weergegeven in deze test:

@Test openbare ongeldig gegevenRegexWithDotEsc_whenMatchingStr_thenNotMatching () {String strInput = "foof"; String strRegex = "foo \."; assertEquals (false, strInput.matches (strRegex)); }

Hier is het punt-teken ontsnapt, dus de matcher behandelt het eenvoudig als een punt en probeert een patroon te vinden dat eindigt met de punt (d.w.z. foo.).

In dit geval keert het terug false omdat er geen overeenkomst is in de invoer Draad voor dat patroon.

3.2. Ontsnappen met behulp van \ Q & \ E

Als alternatief kunnen we gebruiken \ Q en \ E om aan het speciale karakter te ontsnappen. \ Q geeft aan dat alle karakters tot \ E moet worden ontsnapt en \ E betekent dat we een einde moeten maken aan het ontsnappen waarmee begonnen is \ Q.

Dit betekent gewoon dat wat er ook tussen zit \ Q en \ E zou worden ontsnapt.

In de hier getoonde test is de splitsen () van de Draad class doet een overeenkomst met behulp van de reguliere expressie die eraan is verstrekt.

Onze vereiste is om de invoerstring door het pipe-teken (|) in woorden te splitsen. Daarom gebruiken we een reguliere expressiepatroon om dit te doen.

Het pipe-teken is een metateken dat moet worden ontsnapt in de reguliere expressie.

Hier wordt het ontsnappen gedaan door het pijpteken ertussen te plaatsen \ Q en \ E:

@Test openbare leegte gegevenRegexWithPipeEscaped_whenSplitStr_thenSplits () \ E "; assertEquals (4, strInput.split (strRegex) .length); 

4. Het Pattern.quote (String S) Methode

De Pattern.Quote (String S) -methode in java.util.regex.Pattern class converteert een bepaald reguliere-expressiepatroon Draad in een letterlijk patroon Draad. Dit betekent dat alle metatekens in de invoer Draad worden behandeld als gewone karakters.

Het gebruik van deze methode zou een handiger alternatief zijn dan het gebruik van \ Q & \ E terwijl het het gegeven omhult Draad met hen.

Laten we deze methode in actie zien:

@Test openbare leegte gegevenRegexWithPipeEscQuoteMeth_whenSplitStr_thenSplits () balk

In deze snelle test is de Pattern.quote () methode wordt gebruikt om aan het gegeven regex-patroon te ontsnappen en het om te zetten in een Draad letterlijk. Met andere woorden, het ontsnapt voor ons aan alle metatekens die in het regex-patroon aanwezig zijn. Het doet een soortgelijk werk als \ Q & \ E.

Het pipe-teken wordt ontsnapt door de Pattern.quote () methode en de splitsen () interpreteert het als een Draad letterlijk waardoor het de invoer verdeelt.

Zoals we kunnen zien, is dit een veel schonere benadering en ook hoeven de ontwikkelaars niet alle ontsnappingssequenties te onthouden.

Dat moeten we opmerken Patroon. Citaat omsluit het hele blok met een enkele escape-reeks. Als we tekens afzonderlijk willen escapen, moeten we een algoritme voor het vervangen van tokens gebruiken.

5. Aanvullende voorbeelden

Laten we eens kijken hoe de vervang alles() methode van java.util.regex.Matcher werken.

Als we alle exemplaren van een bepaald teken moeten vervangen Draad bij een andere kunnen we deze methode gebruiken door er een reguliere expressie aan door te geven.

Stel je voor dat we een invoer hebben met meerdere keren dat de $ karakter. Het resultaat dat we willen krijgen is dezelfde string met de $ karakter vervangen door £.

Deze test laat zien hoe het patroon $ wordt gepasseerd zonder te worden ontsnapt:

@Test openbare leegte gegevenRegexWithDollar_whenReplacing_thenNotReplace () {String strInput = "Ik heb $ 50 aan mijn broer gegeven." + "Hij kocht snoep voor $ 35. Nu heeft hij $ 15 over."; String strRegex = "$"; String strReplacement = "£"; String output = "Ik heb £ 50 aan mijn broer gegeven." + "Hij kocht snoep voor £ 35. Nu heeft hij £ 15 over."; Pattern p = Pattern.compile (strRegex); Matcher m = p.matcher (strInput); assertThat (output, not (equalTo (m.replaceAll (strReplacement)))); }

De test stelt dat $ is niet correct vervangen door £.

Als we nu aan het regex-patroon ontsnappen, gebeurt het vervangen correct en slaagt de test zoals weergegeven in dit codefragment:

@Test openbare leegte gegevenRegexWithDollarEsc_whenReplacing_thenReplace () {String strInput = "Ik heb $ 50 aan mijn broer gegeven." + "Hij kocht snoep voor $ 35. Nu heeft hij $ 15 over."; String strRegex = "\ $"; String strReplacement = "£"; String output = "Ik heb £ 50 aan mijn broer gegeven." + "Hij kocht snoep voor £ 35. Nu heeft hij £ 15 over."; Pattern p = Pattern.compile (strRegex); Matcher m = p.matcher (strInput); assertEquals (output, m.replaceAll (strReplacement)); }

Merk op \\$ hier, wat de truc doet door te ontsnappen aan de $ karakter en met succes het patroon matchen.

6. Conclusie

In dit artikel hebben we gekeken naar ontsnappende tekens in reguliere expressies in Java.

We bespraken waarom reguliere expressies moeten worden ontsnapt, en de verschillende manieren waarop dit kan worden bereikt.

Zoals altijd is de broncode met betrekking tot dit artikel te vinden op GitHub.