Java Reguliere Expressies: Patroonherkenning onder de knie krijgen met java.util.regex
Java biedt het java.util.regex pakket voor patroonherkenning met reguliere expressies. Java reguliere expressies zijn erg vergelijkbaar met de Perl programmeertaal en heel gemakkelijk te leren.
Een reguliere expressie is een speciale tekenreeks die helpt om andere tekenreeksen of sets van tekenreeksen te matchen of te vinden, met behulp van een gespecialiseerde syntax die in een patroon wordt vastgelegd. Ze kunnen worden gebruikt om te zoeken, bewerken of manipuleren van tekst en data.
Het java.util.regex pakket bestaat primair uit de volgende drie klassen:
Pattern Class – Een Pattern-object is een gecompileerde representatie van een reguliere expressie. De Pattern-klasse biedt geen publieke constructors. Om een patroon te maken, moet u eerst een van de publieke statische compile() methoden aanroepen, die dan een Pattern-object retourneert. Deze methoden accepteren een reguliere expressie als eerste argument.
Matcher Class – Een Matcher-object is de motor die het patroon interpreteert en match-bewerkingen uitvoert tegen een invoertekenreeks. Net als de Pattern-klasse definieert Matcher geen publieke constructors. U verkrijgt een Matcher-object door de matcher() methode aan te roepen op een Pattern-object.
PatternSyntaxException – Een PatternSyntaxException-object is een unchecked exception die een syntaxisfout in een reguliere expressie patroon aangeeft.
Capturing Groups (Vangstgroepen)
Vangstgroepen zijn een manier om meerdere tekens als een enkele eenheid te behandelen. Ze worden gecreëerd door de te groeperen tekens tussen haakjes te plaatsen. Bijvoorbeeld, de reguliere expressie (dog) creëert een enkele groep met de letters "d", "o" en "g".
Vangstgroepen worden genummerd door hun openende haakjes van links naar rechts te tellen. In de expressie ((A)(B(C))), zijn er bijvoorbeeld vier dergelijke groepen:
- ((A)(B(C)))
- (A)
- (B(C))
- (C)
Om te ontdekken hoeveel groepen in de expressie aanwezig zijn, roept u de groupCount-methode aan op een matcher-object. De groupCount-methode retourneert een int dat het aantal vangstgroepen in het patroon van de matcher weergeeft.
Er is ook een speciale groep, groep 0, die altijd de gehele expressie vertegenwoordigt. Deze groep is niet opgenomen in het totaal gerapporteerd door groupCount.
Voorbeeld
Het volgende voorbeeld illustreert hoe u een cijferreeks kunt vinden in een gegeven alfanumerieke tekenreeks:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
public static void main(String args[]) {
// Te scannen tekenreeks om het patroon te vinden
String line = "This order was placed for QT3000! OK?";
String pattern = "(.*)(\\d+)(.*)";
// Maak een Pattern-object
Pattern r = Pattern.compile(pattern);
// Maak nu een matcher-object
Matcher m = r.matcher(line);
if (m.find()) {
System.out.println("Found value: " + m.group(0));
System.out.println("Found value: " + m.group(1));
System.out.println("Found value: " + m.group(2));
} else {
System.out.println("NO MATCH");
}
}
}
Dit produceert het volgende resultaat:
Found value: This order was placed for QT3000! OK? Found value: This order was placed for QT300 Found value: 0
Reguliere Expressie Syntaxis
Hier is de tabel met alle reguliere expressie metateken-syntax beschikbaar in Java:
| Subexpressie | Matches |
|---|---|
| ^ | Matcht het begin van de regel. |
| $ | Matcht het einde van de regel. |
| . | Matcht elk enkel teken behalve newline. Met m optie matcht het ook newline. |
| [...] | Matcht elk enkel teken tussen haakjes. |
| [^...] | Matcht elk enkel teken niet tussen haakjes. |
| \A | Begin van de volledige tekenreeks. |
| \z | Einde van de volledige tekenreeks. |
| \Z | Einde van de volledige tekenreeks behalve toelaatbare finale line terminator. |
| re* | Matcht 0 of meer voorkomens van de voorgaande expressie. |
| re+ | Matcht 1 of meer van het vorige element. |
| re? | Matcht 0 of 1 voorkomen van de voorgaande expressie. |
| re{n} | Matcht precies n aantal voorkomens van de voorgaande expressie. |
| re{n,} | Matcht n of meer voorkomens van de voorgaande expressie. |
| re{n,m} | Matcht minstens n en maximaal m voorkomens van de voorgaande expressie. |
| a|b | Matcht ofwel a ofwel b. |
| (re) | Groepeert reguliere expressies en onthoudt de gematchde tekst. |
| (?:re) | Groepeert reguliere expressies zonder de gematchde tekst te onthouden. |
| (?>re) | Matcht het onafhankelijke patroon zonder backtracking. |
| \w | Matcht woordtekens. |
| \W | Matcht niet-woordtekens. |
| \s | Matcht witruimte. Equivalent aan [\t\n\r\f]. |
| \S | Matcht niet-witruimte. |
| \d | Matcht cijfers. Equivalent aan [0-9]. |
| \D | Matcht niet-cijfers. |
| \A | Matcht het begin van de tekenreeks. |
| \Z | Matcht het einde van de tekenreeks. Als een newline bestaat, matcht het net voor de newline. |
| \z | Matcht het einde van de tekenreeks. |
| \G | Matcht het punt waar de laatste match eindigde. |
| \n | Back-referentie naar vangstgroep nummer "n". |
| \b | Matcht woordgrenzen buiten haakjes. Matcht backspace (0x08) binnen haakjes. |
| \B | Matcht niet-woordgrenzen. |
| \n, \t, etc. | Matcht newlines, carriage returns, tabs, etc. |
| \Q | Escape (quote) alle tekens tot \E. |
| \E | Beëindigt quoteren begonnen met \Q. |
Methoden van de Matcher Class
Index Methoden
Index methoden bieden nuttige indexwaarden die precies tonen waar de match in de invoertekenreeks is gevonden:
| Nr. | Methode & Beschrijving |
|---|---|
| 1 | public int start() – Retourneert de startindex van de vorige match. |
| 2 | public int start(int group) – Retourneert de startindex van de subsequentie gevangen door de gegeven groep tijdens de vorige match-bewerking. |
| 3 | public int end() – Retourneert de offset na het laatste gematchte teken. |
| 4 | public int end(int group) – Retourneert de offset na het laatste teken van de subsequentie gevangen door de gegeven groep tijdens de vorige match-bewerking. |
Study Methoden
Study methoden onderzoeken de invoertekenreeks en retourneren een Boolean die aangeeft of het patroon is gevonden:
| Nr. | Methode & Beschrijving |
|---|---|
| 1 | public boolean lookingAt() – Probeert de invoersequentie, startend aan het begin van de regio, te matchen tegen het patroon. |
| 2 | public boolean find() – Probeert de volgende subsequentie van de invoersequentie te vinden die het patroon matcht. |
| 3 | public boolean find(int start) – Reset deze matcher en probeert dan de volgende subsequentie te vinden die matcht, startend bij de gespecificeerde index. |
| 4 | public boolean matches() – Probeert de gehele regio te matchen tegen het patroon. |
Vervangingsmethoden
Vervangingsmethoden zijn nuttig voor het vervangen van tekst in een invoertekenreeks:
| Nr. | Methode & Beschrijving |
|---|---|
| 1 | public Matcher appendReplacement(StringBuffer sb, String replacement) – Implementeert een niet-terminale append-en-vervang stap. |
| 2 | public StringBuffer appendTail(StringBuffer sb) – Implementeert een terminale append-en-vervang stap. |
| 3 | public String replaceAll(String replacement) – Vervangt elke subsequentie die het patroon matcht met de gegeven vervanging. |
| 4 | public String replaceFirst(String replacement) – Vervangt de eerste subsequentie die het patroon matcht met de gegeven vervanging. |
| 5 | public static String quoteReplacement(String s) – Retourneert een letterlijke vervanging String voor de gespecificeerde String. |
De start en end Methoden
Volgend voorbeeld telt hoe vaak het woord "kat" in de invoertekenreeks voorkomt:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static final String REGEX = "\\bkat\\b";
private static final String INPUT = "kat kat kat katte kat";
public static void main(String args[]) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
int count = 0;
while(m.find()) {
count++;
System.out.println("Match nummer " + count);
System.out.println("start(): " + m.start());
System.out.println("end(): " + m.end());
}
}
}
Dit produceert:
Match nummer 1 start(): 0 end(): 3 Match nummer 2 start(): 4 end(): 7 Match nummer 3 start(): 8 end(): 11 Match nummer 4 start(): 19 end(): 22
De start-methode retourneert de startindex van de subsequentie gevangen door de gegeven groep, en end retourneert de index van het laatste gematchte teken plus één.
De matches en lookingAt Methoden
Beide methoden proberen een invoersequentie te matchen tegen een patroon. Het verschil is dat matches de gehele invoersequentie moet matchen, terwijl lookingAt dat niet hoeft.
Beide methoden starten altijd aan het begin van de invoertekenreeks. Voorbeeld:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static final String REGEX = "foo";
private static final String INPUT = "fooooooooooooooooo";
private static Pattern pattern;
private static Matcher matcher;
public static void main(String args[]) {
pattern = Pattern.compile(REGEX);
matcher = pattern.matcher(INPUT);
System.out.println("Current REGEX is: " + REGEX);
System.out.println("Current INPUT is: " + INPUT);
System.out.println("lookingAt(): " + matcher.lookingAt());
System.out.println("matches(): " + matcher.matches());
}
}
Resultaat:
Current REGEX is: foo Current INPUT is: fooooooooooooooooo lookingAt(): true matches(): false
De replaceFirst en replaceAll Methoden
Deze methoden vervangen tekst die een gegeven reguliere expressie matcht. replaceFirst vervangt de eerste voorkomen, replaceAll alle voorkomens.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static String REGEX = "hond";
private static String INPUT = "De hond zegt miauw. " + "Alle honden zeggen miauw.";
private static String REPLACE = "kat";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
INPUT = m.replaceAll(REPLACE);
System.out.println(INPUT);
}
}
Resultaat:
De kat zegt miauw. Alle katten zeggen miauw.
De appendReplacement en appendTail Methoden
De Matcher-klasse biedt ook appendReplacement en appendTail voor tekstvervanging.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexMatches {
private static String REGEX = "a*b";
private static String INPUT = "aabfooaabfooabfoob";
private static String REPLACE = "-";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT);
StringBuffer sb = new StringBuffer();
while(m.find()) {
m.appendReplacement(sb, REPLACE);
}
m.appendTail(sb);
System.out.println(sb.toString());
}
}
Resultaat:
-foo-foo-foo-
PatternSyntaxException Klasse Methodes
Een PatternSyntaxException is een unchecked exception die een syntaxisfout in een reguliere expressie patroon aangeeft. De klasse biedt de volgende methodes:
| Nr. | Methode & Beschrijving |
|---|---|
| 1 | public String getDescription() – Haalt de beschrijving van de fout op. |
| 2 | public int getIndex() – Haalt de foutindex op. |
| 3 | public String getPattern() – Haalt het foutieve reguliere expressie patroon op. |
| 4 | public String getMessage() – Retourneert een multi-line string met beschrijving, index, foutief patroon en visuele indicatie van de foutindex. |
Java
- C# Expressies, Statements & Blokken: Uitgebreide Gids met Praktische Voorbeelden
- Java-operators beheersen: typen, syntax en praktische voorbeelden
- Java Expressies, Statements en Blokken begrijpen
- Java-commentaar: typen, gebruik en best practices
- Java Enhanced For-lus beheersen: syntax, voorbeelden en best practices
- Java Strings beheersen: aanmaken, methodes en best practices
- Java interfaces meesteren: concepten, implementatie en best practices
- Java Try-with-resources meesteren: automatische resource management uitgelegd
- Java Annotaties uitgelegd: typen, plaatsing en praktische voorbeelden
- Java Assertions: een praktische gids voor bugdetectie en codebetrouwbaarheid
- Java Lambda-expressies: Van basis tot Stream API