Dart regular expressions
last modified October 18, 2026
In this article we show how to work with regular expressions in Dart.
Regular expressions are used for text searching and more advanced text manipulation. We find them in tools such as grep and sed, text editors such as vi and Emacs, and programming languages.
RegExp is used to define a regular expression. Dart regular
expressions have the same syntax and semantics as JavaScript regular
expressions. It is a good practice to define the patterns as raw strings
(r'...') so that the backslashes are not interpreted as escape
sequences by Dart.
Dart regex hasMatch
The hasMatch function checks whether the regular expression has a
match in the specified string.
void main() {
final words = <String>['Seven', 'even', 'Maven', 'Amen', 'eleven'];
final rx = RegExp(r'.even');
for (final word in words) {
if (rx.hasMatch(word)) {
print('$word does match');
} else {
print('$word does not match');
}
}
}
In the example, we have five words in a list. We check which words match the
.even regular expression.
final rx = RegExp(r'.even');
We define a regular expression with RegExp. The dot (.)
metacharacter stands for any single character in the text. Therefore, "even"
does not match, because there is no character before "e".
for (final word in words) {
if (rx.hasMatch(word)) {
print('$word does match');
} else {
print('$word does not match');
}
}
We go over the elements of the list and check if the elements match the regular
expression with hasMatch. Note that hasMatch looks for
the pattern anywhere in the string; "Maven" is not matched because its letters
are "aven".
$ dart main.dart Seven does match even does not match Maven does not match Amen does not match eleven does match
Dart regex alternation
The alternation operator | creates a regular expression with several choices.
void main() {
final words = ['Jane', 'Thomas', 'Robert', 'Lucy', 'Beky', 'John', 'Peter', 'Andy'];
final rx = RegExp('Jane|Beky|Robert');
for (final word in words) {
if (rx.hasMatch(word)) {
print('the $word matches');
}
}
}
We have eight names in the list.
final rx = RegExp('Jane|Beky|Robert');
This regular expression looks for "Jane", "Beky", or "Robert" strings.
$ dart main.dart the Jane matches the Robert matches the Beky matches
Dart regex subpatterns
Subpatterns are patterns within patterns. Subpatterns are created with () characters.
void main() {
final words = [
'book',
'bookshelf',
'bookworm',
'bookcase',
'bookish',
'bookkeeper',
'booklet',
'bookmark'
];
final rx = RegExp(r'^book(worm|mark|keeper)?$');
for (final word in words) {
if (rx.hasMatch(word)) {
print('$word does match');
} else {
print('$word does not match');
}
}
}
We find all words that match the subpattern.
final rx = RegExp(r'^book(worm|mark|keeper)?$');
The regular expression uses a subpattern. The anchors ^ and
$ bind the pattern to the whole string. The pattern matches
bookworm, bookmark, bookkeeper, and book.
$ dart main.dart book does match bookshelf does not match bookworm does match bookcase does not match bookish does not match bookkeeper does match booklet does not match bookmark does match
Dart RegExp firstMatch
The firstMatch function returns the first match as a
RegExpMatch, or null if there is none. The
stringMatch function returns just the matched text.
void main() {
const text = 'The Sun was shining; I went for a walk.';
final rx = RegExp(r'\w+ing');
final match = rx.firstMatch(text);
if (match != null) {
print(match.group(0));
print('${match.start}:${match.end}');
}
print(rx.stringMatch('nothing here'));
print(rx.stringMatch('no match'));
}
The pattern finds a word ending in "ing". The match provides the matched text
with group(0) and its position with start and
end. Because the result is nullable, we must check it before use.
$ dart main.dart shining 12:19 nothing null
Dart RegExp allMatches
The allMatches function finds all matches of the given regular
expression. It returns a lazy iterable of RegExpMatch objects.
void main() {
const text = 'The Sun was shining; I went for a walk.';
final rx = RegExp(r'\w+');
final found = rx.allMatches(text);
print('There are ${found.length} words');
for (final match in found) {
print('${match.group(0)} ${match.start}:${match.end}');
}
}
In the example, we find all words in the text.
final rx = RegExp(r'\w+');
The regular expression matches all words; a word is defined here as one or more word characters (letters, digits, and the underscore).
print('There are ${found.length} words');
We print the number of words.
for (final match in found) {
print('${match.group(0)} ${match.start}:${match.end}');
}
We iterate over all found matches and print them and their indexes.
$ dart main.dart There are 9 words The 0:3 Sun 4:7 was 8:11 shining 12:19 I 21:22 went 23:27 for 28:31 a 32:33 walk 34:38
Dart regex capturing groups
Round brackets are used to create capturing groups. This allows us to apply a quantifier to the entire group or to restrict alternation to a part of the regular expression.
void main() {
final sites = ['example.com', 'zetcode.com', 'freebsd.org', 'netbsd.org'];
final rx = RegExp(r'(\w+)\.(\w+)');
for (final site in sites) {
for (final match in rx.allMatches(site)) {
print(match.group(0));
print(match.group(1));
print(match.group(2));
}
print('----------------------');
}
}
In the example, we divide the domain names into two parts by using groups.
final rx = RegExp(r'(\w+)\.(\w+)');
We define two groups with parentheses. The dot character is escaped because it is used in the literal meaning.
for (final match in rx.allMatches(site)) {
We find all matches with allMatches.
print(match.group(0)); print(match.group(1)); print(match.group(2));
The groups are accessed via the group function. The whole match is
available with match.group(0); groupCount gives the
number of groups.
$ dart main.dart example.com example com ---------------------- zetcode.com zetcode com ---------------------- freebsd.org freebsd org ---------------------- netbsd.org netbsd org ----------------------
Dart regex named groups
A group can be given a name with the (?<name>...) syntax. The
named group is then read with namedGroup, which is more readable
than a numeric index.
void main() {
final rx = RegExp(r'(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})');
final match = rx.firstMatch('Released on 2026-10-18.');
if (match != null) {
print(match.namedGroup('year'));
print(match.namedGroup('month'));
print(match.namedGroup('day'));
print(match.groupNames.toList());
}
}
The pattern parses an ISO date. The groupNames property lists the
names of the groups.
$ dart main.dart 2026 10 18 [year, month, day]
Dart regex replace
The replaceAll and replaceFirst methods of
String accept a regular expression. The
replaceAllMapped method computes the replacement from the match.
void main() {
const text = 'The price is 15 dollars and 40 cents.';
print(text.replaceAll(RegExp(r'\d+'), '#'));
print(text.replaceFirst(RegExp(r'\d+'), '#'));
final doubled = text.replaceAllMapped(
RegExp(r'\d+'),
(m) => (int.parse(m.group(0)!) * 2).toString(),
);
print(doubled);
print('John Doe'.replaceAllMapped(
RegExp(r'(\w+) (\w+)'),
(m) => '${m[2]}, ${m[1]}',
));
}
In the last example, the match is indexed directly with m[2], which
is a shortcut for m.group(2). The replacement swaps the first and
last names.
$ dart main.dart The price is # dollars and # cents. The price is # dollars and 40 cents. The price is 30 dollars and 80 cents. Doe, John
Dart regex flags
The RegExp constructor has named parameters for the flags:
caseSensitive (true by default), multiLine,
dotAll, and unicode.
void main() {
final text = 'First line\nsecond line\nthird line';
final ci = RegExp('FIRST', caseSensitive: false);
print(ci.hasMatch(text));
print(RegExp(r'^\w+').allMatches(text).length);
print(RegExp(r'^\w+', multiLine: true).allMatches(text).length);
print(RegExp(r'line.second').hasMatch(text));
print(RegExp(r'line.second', dotAll: true).hasMatch(text));
}
Without multiLine, the anchors ^ and $
match only at the start and end of the whole string. Without
dotAll, the dot does not match a newline.
$ dart main.dart true 1 3 false true
Dart regex split and escape
A regular expression can also be used to split a string. When the pattern comes
from user input, we escape it with RegExp.escape so that special
characters are matched literally.
void main() {
const text = 'one, two;three four';
print(text.split(RegExp(r'[,;\s]+')));
const userInput = 'a.b*c';
final rx = RegExp(RegExp.escape(userInput));
print(rx.pattern);
print(rx.hasMatch('xx a.b*c yy'));
print(rx.hasMatch('xx aXbbc yy'));
}
The text is split at commas, semicolons, and whitespace. The escaped pattern
a\.b\*c matches only the literal text a.b*c.
$ dart main.dart [one, two, three, four] a\.b\*c true false
Source
In this article we covered Dart regular expressions.
Author
List all Dart tutorials.