Java Language
Normale uitdrukkingen
Zoeken…
Invoering
Een reguliere expressie is een speciale reeks tekens die helpt bij het matchen of vinden van andere reeksen of reeksen reeksen, met behulp van een gespecialiseerde syntaxis in een patroon. Java biedt ondersteuning voor het gebruik van reguliere expressies via het pakket java.util.regex
. Dit onderwerp introduceert en helpt ontwikkelaars meer te begrijpen met voorbeelden over hoe reguliere expressies moeten worden gebruikt in Java.
Syntaxis
- Patroon patternName = Pattern.compile (regex);
- Matcher matcherName = patternName.matcher (textToSearch);
- matcherName.matches () // Retourneert true als de textToSearch exact overeenkomt met de regex
- matcherName.find () // Zoekt via textToSearch naar het eerste exemplaar van een substring die overeenkomt met de regex. Volgende aanroepen zoeken de rest van de string.
- matcherName.group (groupNum) // Retourneert de substring binnen een vastleggroep
- matcherName.group (groupName) // Retourneert de substring binnen een benoemde vastleggroep (Java 7+)
Opmerkingen
invoer
U moet de volgende invoer toevoegen voordat u Regex kunt gebruiken:
import java.util.regex.Matcher
import java.util.regex.Pattern
valkuilen
In Java wordt een backslash ontsnapt met een dubbele backslash, dus een backslash in de regex-string moet worden ingevoerd als een dubbele backslash. Als u moet ontsnappen aan een dubbele backslash (om een enkele backslash te matchen met de regex, moet u deze invoeren als een viervoudige backslash.
Belangrijke symbolen uitgelegd
Karakter | Beschrijving |
---|---|
* | Overeenkomen met het voorgaande teken of subexpressie 0 of meer keer |
+ | Overeenkomen met het voorgaande teken of subexpressie 1 of meer keer |
? | Overeenkomen met het voorgaande teken of subexpressie 0 of 1 keer |
Verder lezen
Het regex-onderwerp bevat meer informatie over reguliere expressies.
Capture groepen gebruiken
Als u nodig hebt om een deel van de string te extraheren uit de input string, kunnen we capture groepen van reguliere expressies gebruiken.
In dit voorbeeld beginnen we met een eenvoudige telefoonnummerregex:
\d{3}-\d{3}-\d{4}
Als haakjes aan de regex worden toegevoegd, wordt elke set haakjes als een vastleggroep beschouwd. In dit geval gebruiken we zogenaamde genummerde opnamegroepen:
(\d{3})-(\d{3})-(\d{4})
^-----^ ^-----^ ^-----^
Group 1 Group 2 Group 3
Voordat we het in Java kunnen gebruiken, moeten we niet vergeten de regels van Strings te volgen en aan de backslashes te ontsnappen, wat resulteert in het volgende patroon:
"(\\d{3})-(\\d{3})-(\\d{4})"
We moeten eerst de reguliere expressie patroon samen te stellen om een make Pattern
en dan moeten we een Matcher
om onze input string met het patroon overeenkomen:
Pattern phonePattern = Pattern.compile("(\\d{3})-(\\d{3})-(\\d{4})");
Matcher phoneMatcher = phonePattern.matcher("abcd800-555-1234wxyz");
Vervolgens moet de Matcher de eerste deelreeks vinden die overeenkomt met de regex:
phoneMatcher.find();
Nu kunnen we met de groepsmethode de gegevens uit de tekenreeks extraheren:
String number = phoneMatcher.group(0); //"800-555-1234" (Group 0 is everything the regex matched)
String aCode = phoneMatcher.group(1); //"800"
String threeDigit = phoneMatcher.group(2); //"555"
String fourDigit = phoneMatcher.group(3); //"1234"
Opmerking: Matcher.group()
kan worden gebruikt in plaats van Matcher.group(0)
.
Java 7 introduceerde benoemde capture-groepen. Benoemde opnamegroepen werken hetzelfde als genummerde opnamegroepen (maar met een naam in plaats van een nummer), hoewel er kleine syntaxiswijzigingen zijn. Het gebruik van benoemde vastleggroepen verbetert de leesbaarheid.
We kunnen de bovenstaande code wijzigen om benoemde groepen te gebruiken:
(?<AreaCode>\d{3})-(\d{3})-(\d{4})
^----------------^ ^-----^ ^-----^
AreaCode Group 2 Group 3
Om de inhoud van "AreaCode" te krijgen, kunnen we in plaats daarvan gebruiken:
String aCode = phoneMatcher.group("AreaCode"); //"800"
Regex gebruiken met aangepast gedrag door het patroon te compileren met vlaggen
Een Pattern
kan worden gecompileerd met vlaggen. Als de regex wordt gebruikt als een letterlijke String
, gebruik dan inline modifiers:
Pattern pattern = Pattern.compile("foo.", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
pattern.matcher("FOO\n").matches(); // Is true.
/* Had the regex not been compiled case insensitively and singlelined,
* it would fail because FOO does not match /foo/ and \n (newline)
* does not match /./.
*/
Pattern anotherPattern = Pattern.compile("(?si)foo");
anotherPattern.matcher("FOO\n").matches(); // Is true.
"foOt".replaceAll("(?si)foo", "ca"); // Returns "cat".
Escape-personages
Over het algemeen
Als u reguliere expressie-specifieke tekens ( ?+|
Enz.) In hun letterlijke betekenis wilt gebruiken, moet u ze laten ontsnappen. In gewone reguliere expressie wordt dit gedaan door een backslash \
. Omdat het echter een speciale betekenis heeft in Java Strings, moet u een dubbele backslash gebruiken \\
.
Deze twee voorbeelden zullen niet werken:
"???".replaceAll ("?", "!"); //java.util.regex.PatternSyntaxException
"???".replaceAll ("\?", "!"); //Invalid escape sequence
Dit voorbeeld werkt
"???".replaceAll ("\\?", "!"); //"!!!"
Een door pijp gescheiden string splitsen
Dit levert niet het verwachte resultaat op:
"a|b".split ("|"); // [a, |, b]
Dit levert het verwachte resultaat op:
"a|b".split ("\\|"); // [a, b]
Ontsnappen aan backslash \
Dit geeft een foutmelding:
"\\".matches("\\"); // PatternSyntaxException
"\\".matches("\\\"); // Syntax Error
Dit werkt:
"\\".matches("\\\\"); // true
Overeenkomend met een regex letterlijk.
Als u tekens moet matchen die deel uitmaken van de syntaxis van de reguliere expressie, kunt u het patroon geheel of gedeeltelijk als een letterlijk regex markeren.
\Q
markeert het begin van de letterlijke regex. \E
markeert het einde van de regex letterlijk.
// the following throws a PatternSyntaxException because of the un-closed bracket
"[123".matches("[123");
// wrapping the bracket in \Q and \E allows the pattern to match as you would expect.
"[123".matches("\\Q[\\E123"); // returns true
Een eenvoudigere manier om dit te doen zonder de Escape-volgorde \Q
en \E
te hoeven onthouden, is om Pattern.quote()
"[123".matches(Pattern.quote("[") + "123"); // returns true
Komt niet overeen met een gegeven string
Om iets dat niet een gegeven string bevat overeenkomen, kan men gebruik maken van negatieve vooruitkijken:
Regex-syntaxis: (?!string-to-not-match)
Voorbeeld:
//not matching "popcorn"
String regexString = "^(?!popcorn).*$";
System.out.println("[popcorn] " + ("popcorn".matches(regexString) ? "matched!" : "nope!"));
System.out.println("[unicorn] " + ("unicorn".matches(regexString) ? "matched!" : "nope!"));
Output:
[popcorn] nope!
[unicorn] matched!
Overeenkomen met een backslash
Als je een backslash in je reguliere expressie wilt matchen, moet je eraan ontsnappen.
Backslash is een escape-personage in reguliere expressies. U kunt '\\' gebruiken om naar een enkele backslash in een reguliere expressie te verwijzen.
Backslash is echter ook een ontsnappingskarakter in letterlijke tekenreeksen van Java. Om een reguliere uitdrukking van een letterlijke tekenreeks te maken, moet je aan elk van de backslashes ontsnappen. In een string kan letterlijk '\\\\' worden gebruikt om een reguliere expressie met '\\' te maken, die op zijn beurt kan overeenkomen met '\'.
Overweeg bijvoorbeeld om overeenkomende tekenreeksen zoals "C: \ dir \ myfile.txt" te zoeken. Een reguliere expressie ([A-Za-z]):\\(.*)
Komt overeen en geeft de stationsletter als een vastleggroep. Let op de dubbele backslash.
Om dat patroon uit te drukken in een letterlijke Java-string, moet elk van de backslashes in de reguliere expressie worden ontsnapt.
String path = "C:\\dir\\myfile.txt";
System.out.println( "Local path: " + path ); // "C:\dir\myfile.txt"
String regex = "([A-Za-z]):\\\\.*"; // Four to match one
System.out.println("Regex: " + regex ); // "([A-Za-z]):\\(.*)"
Pattern pattern = Pattern.compile( regex );
Matcher matcher = pattern.matcher( path );
if ( matcher.matches()) {
System.out.println( "This path is on drive " + matcher.group( 1 ) + ":.");
// This path is on drive C:.
}
Als je twee backslashes wilt matchen, merk je dat je acht gebruikt in een letterlijke string, om vier in de reguliere expressie te vertegenwoordigen, om twee te matchen.
String path = "\\\\myhost\\share\\myfile.txt";
System.out.println( "UNC path: " + path ); // \\myhost\share\myfile.txt"
String regex = "\\\\\\\\(.+?)\\\\(.*)"; // Eight to match two
System.out.println("Regex: " + regex ); // \\\\(.+?)\\(.*)
Pattern pattern = Pattern.compile( regex );
Matcher matcher = pattern.matcher( path );
if ( matcher.matches()) {
System.out.println( "This path is on host '" + matcher.group( 1 ) + "'.");
// This path is on host 'myhost'.
}