Regulaaravaldised

Regulaaravaldis on formaalne viis tekstis leiduva mustri kirja panemiseks. Selle abil saame tekstist mingeid asju üles otsida ning ka neid asendada.

Javas otsest regulaaravaldise klassi pole, selle asemel on pakk java.util.regex, mille sees on meil järgnevad klassid:

  • Pattern - Klass, mis defineerib ära kompileeritud mustri, mida kasutatakse otsingus.

  • MatchResult - Liides otsingutulemuse jaoks.

  • Matcher - Klass, mida kasutatakse mustri tööle panemiseks.

  • PatternSyntaxException - Erindi klass, mis annab märku, et muster on valesti koostatud.

Keskendume siin artiklis Pattern ja Matcher-ile.

Pattern

Pattern klass on kompileeritud regulaaravaldis.

Klassil avaliku konstruktorit pole, Pattern instantsi koostamine käib järgnevalt:

import java.util.regex.*;

public class Example {
    public static void main(String[] args) {
        // Compiles a pattern, that finds text with prefix "word:" and the following text
        Pattern pattern = Pattern.compile("word:\\w*");

        // If we want to add flags, we can add it as a parameter
        Pattern patternWithFlags = Pattern.compile("word:[a-z]*", Pattern.CASE_INSENSITIVE);

        // If we want to add multiple flags, separate them with "|"
        Pattern patternWithMultiFlags = Pattern.compile("word:[a-z]*", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
    }
}

Peale mustri kompileerimist saame seda kasutada Matcher klassis, et otsinguid läbi viia.

Kompileerimise ajal on võimalik ka igasugu lippe kaasa anda parameetritena, nendeks on:

  • Pattern.CANON_EQ - Kui antud lipp on kasutusel, siis kaks tähemärki on omavahel võrdelised ainult siis, kui nad lagunduvad kanooniliselt samaks. Näiteks regulaaravaldisega a\u030A leiab vastandi sõnest \u00E5. Vaikimisi antud käitumine pole sisse lülitatud.

  • Pattern.CASE_INSENSITIVE - Muudab avaldise tõusutundetuks.

  • Pattern.COMMENTS - Lubab kasutada regulaaravaldises tühikuid ning kommentaare.

  • Pattern.DOTALL - Lubab leida igat tähte, mida võimalik (sh ka realõppu).

  • Pattern.LITERAL - Kohtleb sisendmustrit sõnasõnaliselt ehk eirab igasugu lippe, mis mustris sees on (kohtleb neid kui tavalisi tähti).

  • Pattern.MULTILINE - Lubab leida teksti iga rea algusest/lõpust. Vaikimisi otsid sõne algusest/lõpust.

  • Pattern.UNICODE_CASE - Kui kasutada koos CASE_INSENSITIVE lipuga, siis tõusutundetusel arvestatakse ka unicode tähemärkidega.

  • Pattern.UNICODE_CHARACTER_CLASS - Lubab kasutada unicode versiooone tähemärkidest (US-ASCII ja POSIX tähemärkide asemel).

  • Pattern.UNIX_LINES - Kasutab reavahetusteks \n tähemärki.

Otse Pattern klassist otsingu läbi viimiseks:

import java.util.regex.*;

public class Example {
    public static void main(String[] args) {
        boolean found = Pattern.compile("word:\\w*").matcher("test word:cat!!!").find();    // If you want to use stuff like find()

        // or

        boolean matches = Pattern.matches("word:\\w*", text);   // Can only match
    }
}

Matcher

Matcher klassist luuakse objekt, millega otsinguid läbi viia.

Matcheri loomiseks tuleb kompileeritud Pattern-ist välja kutsuda .matcher(CharSequence input) meetod.

import java.util.regex.*;

public class Example {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile("word:\\w*");
        Matcher matcher = pattern.matcher("Example: aaa word:cat!!!");
    }
}

Kui Matcher on loodud, saame selle peal läbi viia kolme tegevust:

  • matches() - Kontrollib, kas terve sisend on vastavuses regulaaravaldisele.

  • lookingAt() - Üritab leida terve sisendi raames mingit osa, mis on vastavuses regulaaravaldisega. Alustab algusest.

  • find() - Nullib eelnevad tulemused ning üritab leida sisendist järgmist alamosa, mis on vastavuses regulaaravaldisega. Alustab kas algusest või eelmise otsingu lõpust. Saab juurde anda ka täisarvulise parameetri, mis tähistab algus-indeksi.

Kõik kolm meetodit tagastavad tõeväärtuse. True, kui leidus midagi, vastasel juhul false. Kui otsing oli edukas, saab edaspidi kasutada mõningaid meetodeid, näiteks start() ja end(), et leida leitud alamosa algus- ja lõppindeks.

import java.util.regex.*;

public class Example {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile("word:\\w*");
        Matcher matcher = pattern.matcher("Example: aaa word:cat!!! here is another word:dog.....");

        // Each time a match is found, matcher stops.
        while(matcher.find()) {
            System.out.println(matcher.group());    // Returns the last found match
            System.out.println(matcher.start());    // Returns it's starting index
            System.out.println(matcher.end());      // Returns it's ending index
        }
    }
}

Matcheri otsingut saab piirata kasutades meetodit region(start, end), mis määrab ära algus- ja lõpppunkti, mille raames otsing viiakse läbi. Matcheri saab nullida ära meetodiga reset().

import java.util.regex.*;

public class Example {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile("java");
        Matcher matcher = pattern.matcher("java python c++ c# java is the best!!");

        System.out.println(matcher.matches());  // Doesn't find anything because it tries to match the whole region

        matcher.region(0, 4);                   // Limiting region to first word
        System.out.println(matcher.matches());  // Now it can match just as fine

        matcher.reset();                        // Resets the matcher
    }
}

Uuri lisaks:

Pattern: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/regex/Pattern.html

Matcher: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/regex/Matcher.html