Regex Reluctant (Lazy) Quantifiers Tutorial

There are three different groupings of quantifiers: greedy, reluctant, and possessive. This tutorial is all about reluctant quantifiers; reluctant quantifiers are also commonly referred to as lazy quantifiers. In my Regex Greedy Quantifiers Tutorial we learned that greedy quantifiers instruct the matcher to match as many instances of its quantified token and return the largest possible string value. Reluctant quantifiers instruct the matcher to match each individual instance of a quantified token and return the smallest possible string value. Since reluctant quantifiers return the smallest possible value, you will often see that the Matcher class .find() method will return true multiple times versus just a single time with a greedy quantifier. The syntax for reluctant quantifiers is the same as greedy quantifiers only you will simply tack a ? on to the greedy quantifier to turn in into a reluctant quantifier.
     ?? once or not at all
     *? zero or more times
     +? one or more times
     {x}? exactly x times
     {x,}? at least x times
     {x,y}? at least x but not more than y times

The difference between the behavior of reluctant and greedy quantifiers in most cases is not obvious at all. The examples below are identical - only with the reluctant modifier added - to the examples that I used in my greedy tutorial and you can see that they will return the exact same results:
     colou??r · will match color or colour
     colou*?r · will match color or colour
     colou{0,}?r · will match color or colour
     M(i\\w\\w)*?i · will match Mississippi
     M(i\\w\\w)+?i · will match Mississippi
     M(i\\w\\w){3}?i · will match Mississippi
     M(i\\w\\w){0,}?i · will match Mississippi
     M(i\\w\\w){1,}?i · will match Mississippi

The differences become apparent when you have repeating patterns inside of your search string. Consider the following search string:
     "<xml>YES</xml> <xml>NO</xml>"
     <xml>.*</xml> ·
will return <xml>YES</xml> <xml>NO</xml>
     <xml>.*?</xml> ·
will return <xml>YES</xml> on the first call to .find() and <xml>NO</xml> on the second one.



Open the command prompt (CMD - see the Getting Started ) and type in the following commands.

C:\Windows\System32>cd \
C:\>md Java
C:\>cd Java
C:\Java>
C:\Java>md RegexReluctantQuantifiers
C:\Java>cd RegexReluctantQuantifiers
C:\Java\RegexReluctantQuantifiers>Notepad RegexReluctantQuantifiers.java

Copy and Paste, or type the following code into Notepad and be sure to save the file when you are done.


import java.util.regex.*;

class RegexReluctantQuantifiers {
    public static void main(String args[]) {
        displayFind("colou??r", "Is that a coloring book?");
        displayFind("colou??r", "Is that a colouring book?");
        displayFind("colou*?r", "Is that a coloring book?");
        displayFind("colou*?r", "Is that a colouring book?");
        displayFind("colou+?r", "Is that a coloring book?");
        displayFind("colou+?r", "Is that a colouring book?");
        displayFind("colou{0,}?r", "Is that a coloring book?");
        displayFind("colou{0,}?r", "Is that a colouring book?");
        displayFind("M(i\\w\\w)*?i", "The Mississippi river");
        displayFind("M(i\\w\\w){0,}?i", "The Mississippi river");
        displayFind("M(i\\w\\w)+?i", "The Mississippi river");	
        displayFind("M(i\\w\\w){1,}?i", "The Mississippi river");
        displayFind("M(i\\w\\w){3}?i", "The Mississippi river");
        System.out.println();

        displayFind("<xml>.*</xml>", "<xml>YES</xml> <xml>NO</xml>");
        displayFind("<xml>.*?</xml>", "<xml>YES</xml> <xml>NO</xml>");
        System.out.println();

        //here comes the confusion...
        displayFind("1?",  "01100111"); // 103 greedy - largest possible match!
        displayFind("1??", "01100111"); // reluctant - smallest possible match!
        System.out.println();
        displayFind("1*",  "01100111"); // greedy - largest possible match!
        displayFind("1*?", "01100111"); // reluctant - smallest possible match!
        System.out.println();
        displayFind("1+",  "01100111"); // greedy - largest possible match!
        displayFind("1+?", "01100111"); // reluctant - smallest possible match!
        System.out.println();
        displayFind("1{2}",  "01100111"); // greedy - largest possible match!
        displayFind("1{2}?", "01100111"); // reluctant - smallest possible match!
        System.out.println();
        displayFind("1{2,}",  "01100111"); // greedy - largest possible match!
        displayFind("1{2,}?", "01100111"); // reluctant - smallest possible match!
        System.out.println();
        displayFind("1{2,3}",  "01100111"); // greedy - largest possible match!
        displayFind("1{2,3}?", "01100111"); // reluctant - smallest possible match!
        System.out.println();

        displayFind("happy.*dogs", "I like happy large dogs and happy small dogs!");
        displayFind("happy.*?dogs", "I like happy large dogs and happy small dogs!");
        System.out.println();

    }

    static void displayFind(String regex, String searchMe) {
        boolean foundIt = false;
        Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(searchMe);
        while(m.find()){
            System.out.println("Regex " + regex + " found " + m.group() +  " in \"" + searchMe +"\"" );
            foundIt = true;
        }
        if(!foundIt){
            System.out.println("No matches found for " + regex + " in string \"" + searchMe +"\"");
        }  
    }
}

Now switch back to the command prompt (CMD) and type in javac RegexReluctantQuantifiers.java and press Enter.
Now type in java RegexReluctantQuantifiers and press Enter.


C:\Java\RegexReluctantQuantifiers>javac RegexReluctantQuantifiers.java
C:\Java\RegexReluctantQuantifiers>java RegexReluctantQuantifiers
See video for explanation


Final thoughts

At this point if you are experiencing confusion or frustration, then you may want to wait a day then watch it again. Sometimes new concepts take some time to sink in. Stay tuned to my next tutorial where I will demonstrate possessive quantifiers and show you how they behave differently from both greedy and reluctant ones.


Tutorials