Java Arena
Step 3 of 8

Regular expressions: matches, | and groups

Is KTX-0415 a booking code of the right form? Is 9021O a postcode, or a typo with the letter O in it? Checking the form of a string with charAt and loops takes many lines. A regular expression, or regex for short, describes a form in one short String, and String's method matches checks whether a string has that form.

matches

System.out.println("yes".matches("yes"));
System.out.println("Yes".matches("yes"));
System.out.println("yes!".matches("yes"));
Output
true
false
false
  • Letters and digits in a regex stand for themselves, so the regex yes describes exactly the text yes.
  • Upper and lower case differ, as they do for equals.
  • The whole string must fit the regex: yes! has a ! left over.

So far, that's what equals does. The rest of this step and the next are what equals can't do.

Alternation: |

A | means "or". The regex yes|y|ok describes three texts, and a string matches if it's any one of them:

String[] answers = {"yes", "y", "ok", "okay", "no"};
for (String answer : answers) {
    System.out.println(answer + ": " + answer.matches("yes|y|ok"));
}
Output
yes: true
y: true
ok: true
okay: false
no: false

okay begins with ok, but the whole string has to fit one of the three.

Groups: ( )

A | splits the whole regex in two. A ferry sells four kinds of tickets: adult single, adult return, child single and child return. The regex adult|child single|return would mean three choices: adult, child single or return. Parentheses make a group, and a | inside a group chooses only there:

String ticket = "(adult|child) (single|return)";
System.out.println("child return".matches(ticket));
System.out.println("adult single".matches(ticket));
System.out.println("adult".matches(ticket));
System.out.println("senior single".matches(ticket));
Output
true
true
false
false

The regex describes four texts: one of the words in the first group, a space, and one of the words in the second group. A group can be a part of a word, too: gr(a|e)y matches both gray and grey.

System.out.println("grey".matches("gr(a|e)y") + " " + "gray".matches("gr(a|e)y") + " " + "groy".matches("gr(a|e)y"));
Output
true true false

Characters with a meaning of their own

|, ( and ) aren't matched as themselves: they're part of the regex's own language. So are a few more characters, . * + ? [ { ^ $ \, and also ] and } when they close a [ or a {. Step 4 gives most of them their meaning. (^ and $ mark the start and the end of the text, which matches checks anyway.) Letters, digits, spaces, dashes and colons are plain characters. To match a special character as itself, put \\ in front of it in the Java String: in a regex, a backslash takes the special meaning away, and in a Java String, \\ is how you write one backslash.

System.out.println("(1)".matches("\\(1\\)"));
Output
true

Your task

Challenge 1 of 3

An ice cream stand sells four things: single cone, single cup, double cone and double cup. Fill in the regex, with two groups, so that it describes exactly those four. The program then prints:

single cone: true
double cup: true
single cup: true
double cone: true
triple cone: false
double: false
single cones: false

Challenge 2

What does this program print?

Challenge 3

The text UI of a notes app, like the ones in module 25, understands six commands: add note, add task, remove note, remove task, list and quit. Write the method isCommand(String line), which returns whether a line is one of them, with a single call to matches. The check runs:

System.out.println(isCommand("add task"));
System.out.println(isCommand("list"));
System.out.println(isCommand("list task"));
System.out.println(isCommand("add"));

and expects:

true
true
false
false