Match Boundaries


By default, when a pattern matches a string the entire match is returned. For example, suppose we have a buffer that contains a number of dates:

Initial Conditions
2022-01-14
2022-07-09
2022-10-23
2022-12-20
2023-01-26
2023-03-17
2023-08-06
2023-11-05
COMMANDTop1:1
/2022-1\d-\d\d

Suppose we wanted to edit all dates that occur in Q4 (months 10, 11, and 12) of 2022. Our first thought might be to define capturing groups then use back-references to search and replace to make the necessary edits. This is a great solution when the edits are well-defined, but this hypothetical scenario requires us to manually-edit the dates.

Our next thought might be to search for all dates that meet these constraints with a pattern such as:

2022-1\d-\d\d
Search with generic pattern
2022-01-14
2022-07-09
2022-10-23
2022-12-20
2023-01-26
2023-03-17
2023-08-06
2023-11-05
NORMAL33%3:1
 

then jump to a result, move the cursor to the month and day, make the necessary edits, then repeat the search for each match. This works, but can be improved.

Our pattern matches to correct lines, but returns the entire date when we only want the month and date. This is a good use-case for adding match boundaries.

At a high-level, match boundaries break the searching process up into two steps:

  1. The entire pattern is used to define which text to matched, then
  2. The match boundaries define which portion of the matched text to return

Match boundaries are defined using one or both of the following markers:

Shortcut Definition
\zs Defines where the matched text will start
\ze Defines where the matched text will end

When \zs is present, the match will start with the character immediately to the right of it. Likewise, when \ze is present, the match will end with the character immediately to the left of it.

Back to our example, our current pattern does a good job of matching the correct lines in the buffer, we just need to isolate the match to the month and date. This can be done by defining the starting boundary:

2022-\zs1\d-\d\d

and executing the search again:

Search with start boundary
2022-01-14
2022-07-09
2022-10-23
2022-12-20
2023-01-26
2023-03-17
2023-08-06
2023-11-05
NORMAL33%3:6
 

Now, when we just from match to match to make our edits, we are already in the correct location. Pretty cool.

To extend the example, let's add an ending boundary to isolate only the month portion of the date:

2022-\zs1\d\ze-\d\d

and execute again:

Search with start and end boundaries
2022-01-14
2022-07-09
2022-10-23
2022-12-20
2023-01-26
2023-03-17
2023-08-06
2023-11-05
NORMAL33%3:6
 

Match boundaries provide an extra degree of freedom that can be leveraged in some cases, such as this.