Understanding `regexp_match()` in QGIS
Learn how the QGIS `regexp_match()` function works, how to interpret its return value, and how to use it to filter features with practical examples.
The regexp_match() function searches a string using a regular expression (regex) and returns the starting position of the first match. If the pattern is not found, it returns 0.
This often causes confusion because when the function is used in tools such as Extract by Expression or Select by Expression, it appears to behave like a Boolean function. In reality, it always returns an integer, but QGIS interprets non-zero values as TRUE and 0 as FALSE when a Boolean result is expected.
Syntax
regexp_match(input_string, regex)
| Argument | Description |
|---|---|
input_string |
The string to search. |
regex |
The regular expression pattern. Backslashes must be escaped in QGIS expressions (for example \\d, \\s, \\b). |
Return Value
The function returns:
- 1 or greater — the position where the first match begins.
- 0 — no match was found.
For example,
regexp_match('Hello World', 'World')
returns
1
7
because World starts at the seventh character.
If the text does not exist,
regexp_match('Hello World', 'Earth')
returns
1
0
Why Does It Work in Extract by Expression?
Suppose the expression is
regexp_match("ref", '^NH')
and the attribute values are:
| ref | Result |
|---|---|
| NH-01 | 1 |
| NH45 | 1 |
| SH-09 | 0 |
| ABC123 | 0 |
The Extract by Expression algorithm expects a Boolean value.
Internally, QGIS converts the results as follows:
| Returned value | Boolean |
|---|---|
| 0 | FALSE |
| Any non-zero number | TRUE |
Therefore,
regexp_match("ref", '^NH')
behaves exactly like
regexp_match("ref", '^NH') > 0
or
regexp_match("ref", '^NH') = 1
because the pattern ^NH can only start at the first character.
Practical Challenge
Assume the karnataka_major_roads layer contains a field named "name" with the following values:
| Road Name | Should Match? |
|---|---|
| 1st Main Road | ✓ |
| 2nd Main Road | ✓ |
| 23rd Main Road | ✓ |
| 101st Main Road | ✓ |
| Banneghatta Main Road | ✗ |
| Old Main Road | ✗ |
| Main Road | ✗ |
The objective is to extract only roads that begin with a numbered ordinal followed by Main Road.
Step 1 — Identify the Pattern
Every valid road follows the same structure:
1
<number><ordinal> Main Road
Examples:
1
2
3
4
1st Main Road
2nd Main Road
23rd Main Road
101st Main Road
Step 2 — Build the Regular Expression
Break the pattern into smaller pieces.
One or More Digits
Regex:
1
\d+
In a QGIS expression:
1
\\d+
Ordinal Suffix
Possible suffixes are:
1
2
3
4
st
nd
rd
th
Regex:
1
(st|nd|rd|th)
The vertical bar (|) means OR.
A Space
Regex:
1
\s
QGIS expression:
1
\\s
Literal Text
1
Main Road
Beginning of the String
To ensure the road name starts with the number:
1
^
End of the String
To prevent matches such as 1st Main Road Extension:
1
$
Complete Regular Expression
Standard regex:
1
^\d+(st|nd|rd|th)\sMain Road$
QGIS expression:
'^\\d+(st|nd|rd|th)\\sMain Road$'
Using regexp_match()
regexp_match(
"name",
'^\\d+(st|nd|rd|th)\\sMain Road$'
)
What Does It Return?
| Road Name | Result |
|---|---|
| 1st Main Road | 1 |
| 2nd Main Road | 1 |
| 23rd Main Road | 1 |
| 101st Main Road | 1 |
| Banneghatta Main Road | 0 |
| Main Road | 0 |
Notice that every valid match begins at the first character, so the function returns 1.
Understanding the Return Value
Consider the road name:
1
23rd Main Road
The regular expression starts matching immediately:
1
2
2 3 r d M a i n R o a d
^
The match begins at the first character.
Result:
1
1
Now consider:
1
Banneghatta Main Road
The regular expression expects
1
^\d+
which means the string must begin with one or more digits.
Instead, the first character is B, so no match exists.
Result:
1
0
Another Example
Suppose the regular expression is simply
'Main Road'
Now the function searches anywhere in the string.
| Road Name | Result |
|---|---|
| 1st Main Road | 5 |
| 23rd Main Road | 6 |
| Banneghatta Main Road | 13 |
For "1st Main Road":
1
2
1 s t _ M a i n _ R o a d
1 2 3 4 5
The substring Main Road begins at character 5, so
regexp_match("name", 'Main Road')
returns
1
5
This demonstrates the real purpose of regexp_match(): it tells you where the first match occurs, not simply whether it exists.
regexp_match() vs LIKE
A LIKE expression such as
"name" LIKE '%Main Road'
would also match
- Banneghatta Main Road
- Old Main Road
- East Main Road
It cannot enforce the rule that the name must start with a numbered ordinal.
The regular expression
regexp_match(
"name",
'^\\d+(st|nd|rd|th)\\sMain Road$'
)
matches only names that satisfy all of the following conditions:
- begin with one or more digits;
- are immediately followed by
st,nd,rd, orth; - contain a single space;
- end with the exact text
Main Road.
Key Points
regexp_match()returns the starting position of the first regex match.- If no match exists, it returns 0.
- In Boolean contexts, 0 is treated as FALSE and any non-zero value as TRUE.
- Anchors such as
^and$make it possible to validate the entire string instead of searching for a substring. - Regular expressions are significantly more powerful than
LIKEwhen matching structured text such as road names, parcel identifiers, postal codes, or formatted reference numbers.