- 常用正则模式
\d: 数字
\w: 字母、数字或下划线
\s: 空白字符
\.: .
^: 字符串开头
$: 字符串结尾
- 量词
*: 0次或多次
+: 1次或多次
?: 0次或1次
{n}: 恰好n次
{n,}: 至少n次
{n,m}: n到m次
- 字符类
[abc]: a、b或c
[a^b^c]: a、非b、非c
[a-z]: a到z任意小写字母
[A-Z]: A到Z任意大写字母
[0-9]: 任意数字
- 分组和捕获
(pattern): 捕获分组(重要)
(?:pattern): 非捕获分组
(?=pattern): 正向预查
(?!pattern): 负向预查
- 用例
- 验证电子邮件
void test() {
String email = 'test@example.com';
String invali_email = 'invalid.email';
var reg = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
print("输出是${reg.hasMatch(email)}"); // true
print("输出是${reg.hasMatch(invali_email)}"); // false
}
- 提取URL中的域名
void test() {
String url = 'https://www.example.com/path';
var reg = RegExp(r'https?://([\w\-\.]+)');
var match = reg.firstMatch(url);
print("输出是${match?.group(1) ?? 'Invalid URL'}"); // 输出是www.example.com
}
- 分组和捕获
功能:将多个字符组合为一个单元;提取匹配的子字符串;在替换或后续匹配中引用已匹配的内容。
- 捕获组。使用圆括号 () 创建捕获组,匹配的内容会被记住并可以通过索引引用。
void test() {
var reg = RegExp(r'(\d{4})-(\d{2})-(\d{2})'); // 匹配日期
var match = reg.firstMatch('1919-08-10');
print("输出是${match?.group(0)}"); // 1919-08-10
print("输出是${match?.group(1)}"); // 1919
print("输出是${match?.group(2)}"); // 08
print("输出是${match?.group(3)}"); // 10
}
- 非捕获组。使用 (?😃 表示非捕获组,它只分组但不记住匹配内容。
void test() {
var reg = RegExp(r'(?:\d{4})-(\d{2})-(\d{2})'); // 匹配日期
var match = reg.firstMatch('1919-08-10');
print("输出是${match?.group(0)}"); // 1919-08-10
print("输出是${match?.group(1)}"); // 08
print("输出是${match?.group(2)}"); // 10
}
- 命名捕获组。Dart 支持通过 (?<name>…) 语法给捕获组命名。
void test() {
var reg = RegExp(r'(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})');
var match = reg.firstMatch('1919-08-10');
print("输出是${match?.namedGroup('year')}"); // 1919
print("输出是${match?.namedGroup('month')}"); // 08
print("输出是${match?.namedGroup('day')}"); // 10
}
- 使用 $n 引用捕获组进行替换:
void test() {
var reg = RegExp(r'(\d{4})-(\d{2})-(\d{2})');
var result = '1919-08-10'.replaceAllMapped(reg, (match) {
return '${match.group(2)}/${match.group(3)}/${match.group(1)}';
});
print("输出是${result}"); // "08/10/1919" (美式日期格式)
}
嵌套分组。分组可以嵌套使用,索引按左括号的顺序分配:
void test() {
var reg = RegExp(r'((\d{4})-(\d{2}))-(\d{2})');
var match = reg.firstMatch('1919-08-10');
print("输出是${match?.group(0)}"); // 1919-08-10
print("输出是${match?.group(1)}"); // 1919-08 (外层分组)
print("输出是${match?.group(2)}"); // 1919 (内层分组1)
print("输出是${match?.group(3)}"); // 08 (内层分组2)
print("输出是${match?.group(4)}"); // 10 (最后一个分组)
}
- 正向预查,表示"后面必须跟着pattern"的位置。
void test() {
// 至少6位且包含数字的密码
var reg = RegExp(r'^(?=.*\d).{6,}$');
print("输出是${reg.hasMatch('abc123')}"); // true
print("输出是${reg.hasMatch('abcdef')}"); // false
}
- 负向预查,表示"后面不能跟着pattern"的位置。
void test() {
// 验证没有连续两个相同字母的字符串
var reg = RegExp(r'^(?!.*(.)\1).*$');
print("输出是${reg.hasMatch('abcde')}"); // true
print("输出是${reg.hasMatch('hello')}"); // false
}
939

被折叠的 条评论
为什么被折叠?



