1. Introduction

Regular expressions are powerful tools for matching and manipulating text in Java. They allow us to specify patterns matching certain characters, words, or phrases in a text. In Java, regular expressions are supported through the java.util.regex package.

Moreover, \z and \Z and $ are three common regular expression anchors that can match the end of a string.

In this tutorial, we’ll explore the difference between these two anchors, how they work, and when to use them.

2. Regular Expression Anchor – \z vs. \Z vs. $

A regular expression anchor is a character or sequence of characters that can specify a position in the text where a match should occur.

All of the \z and \Z and $ are regular expression anchors that can match the end of a string exactly. However, they behave differently when the string ends with a line terminator (such as a newline character).

In general, \z anchor can be used when we want to ensure that a regular expression matches the absolute end of a string, regardless of whether it ends with a line terminator or not. This is useful to ensure no more text after the matching pattern.

On the other hand, \Z is used when we want to ensure that a regular expression matches the end of a string or the end of a line (if the string ends with a line terminator). This is useful when we want to match patterns at the end of each line in a multi-line string.

The $ is functionally equivalent to \z and matches the end of the string without considering line terminators.

3. Examples of When to Use \z, \Z, and $

Now that we understand the difference between \z and \Z, let’s explore real-world scenarios where we might use each anchor.

3.1. Examples of  Using \z

When validating a credit card number, we want to make sure that there are no extra digits or characters after the card number. To achieve this, we can use the \z regular expression. It ensures that the pattern matches only the complete credit card number and not any additional text that might appear after it.

@Test
public void givenCreditCardNumber_thenReturnIfMatched() {
    String creditCardNumber = "1234567890123456";
    String pattern = "\\d{16}\\z";
    Assertions.assertTrue(Pattern.compile(pattern).matcher(creditCardNumber).find());
}

This method validates whether a given credit card number contains exactly 16 digits, using a regular expression pattern match using \z.

On the other hand, when parsing log files, we may want to match patterns at the end of each line. However, we don’t want to include any text from subsequent lines. In this scenario, we can use the \z regular expression to ensure that the pattern matches only the text at the end of a line. Even if the line ends with a line terminator, \z ensures that the pattern matches only the last line.

@Test
public void givenLogOutput_thenReturnIfMatched() {
    String logLine = "2022-05-01 14:30:00,123 INFO Some log message";
    String pattern = ".*message\\z";
    Assertions.assertTrue(Pattern.compile(pattern).matcher(logLine).find());
}

This method takes defines a log line*.* Then it checks if they end with the word “message” followed by the end of the string \z.

3.2. Examples of  Using \Z

When parsing email messages, we often only want to match patterns at the very end of the message body, without including any text from the email signature. To achieve this, we can use the \Z symbol in our regular expression, which ensures that the pattern only matches the text at the very end of the message body.

@Test
public void givenEmailMessage_thenReturnIfMatched() {
    String myMessage = "Hello HR, I hope i can write to Baeldung\n";
    String pattern = ".*Baeldung\\Z";
    Assertions.assertTrue(Pattern.compile(pattern).matcher(myMessage).find());
}

This method checks if the string message ends with the pattern “Baeldung” followed by optional white space characters and then the end of the string \Z.

Similarly, when matching file extensions, we may want to ensure that the regular expression only matches the extension at the very end of the file name. Again, we can use the \Z symbol in our regular expression to ensure that it only matches the extension at the end of the file name.

@Test
public void givenFileExtension_thenReturnIfMatched() {
    String fileName = "image.jpeg\n";
    String pattern = ".*\\.jpeg\\Z";
    Assertions.assertTrue(Pattern.compile(pattern).matcher(fileName).find());
}

This code tests if a file name ends with a specific file extension using \Z regular expression. The method givenFileExtension_thenReturnIfMatched checks if the string file name fileName ends with the extensions .jpeg.

3.3. Examples of Using $

We might want to verify whether a URL matches a specific endpoint when working with URLs. Hence, the $ anchor can help ensure that the pattern matches only if it represents the end of the URL:

@Test
public void givenURL_thenReturnIfMatched() {
    String url = "https://www.example.com/api/endpoint\n";
    String pattern = ".*/endpoint$";
    Assertions.assertTrue(Pattern.compile(pattern).matcher(url).find());
}

In this example, we used the pattern to match any characters before “/endpoint” and ensure that it occurs at the end of the exact string without considering if there is a line terminator or not.

Besides, we can utilize the $ anchor when we want to verify if a sentence ends with proper punctuation, such as a period, question mark, or exclamation mark:

@Test
public void givenSentence_thenReturnIfMatched() {
    String sentence = "Hello, how are you?";
    String pattern = ".*[.?!]$";
    Assertions.assertTrue(Pattern.compile(pattern).matcher(sentence).find());
}

This method checks whether a given sentence ends with a period, question mark, or exclamation mark. In addition, the pattern used in the previous code matches any characters followed by a period, question mark, or exclamation mark, ensuring that it occurs at the end of the string.

4. Conclusion

In conclusion, regular expression anchors are useful in Java for matching patterns in text. \z and \Z are two anchors that match the end of a string, but they behave differently when the string ends with a line terminator. \z ensures that a regular expression matches the absolute end of a string, while \Z matches the end of a string or the end of a line. On the other side, $ anchor is a regular expression construct that specifically matches the end of a string.

By using the appropriate anchor, we can ensure that our regular expressions match only the text we want and not any additional text that might appear after it.

Understanding the differences between \z, \Z, and $ will help us write more accurate regular expressions in our Java code.

The complete source code for this tutorial is available over on GitHub.