前言
正则表达式的匹配模式由一系列数字、文字、运算符、字符等的字符组成,根据自己需求设计对应的模式,实现分析、匹配的操作。本文将对正则表达式组成语法进行讲解。
语法规则
正则表达式构建的匹配模式由转义字符、字符类、定位符、分组构造、限定符、反向引用构造、备用构造、替换、杂项构造等组成。
1、特殊字符:正则表达式中已经具有一定特殊意义的字符
字符 | 描述 |
---|---|
^ | 匹配输入字符串的开始位置 |
$ | 匹配输入字符串的结束位置 |
\ | 将特殊字符变为普通的字符;指定预定义字符集;定义断言 |
? | 匹配前面的字符零次或一次 |
+ | 匹配前面的字符一次或多次 |
* | 匹配前面的字符零次或多次 |
. | 匹配出换行符外的任意一个字符 |
- | 表示字符的匹配范围 |
| | 匹配以竖线字符分隔的任何一个字符 |
示例:
cs
#region ^
// 模式 ^136
string pattern = @"^136";
Console.WriteLine(string.Format("字符串是否以136开头:{0}", Regex.IsMatch("1380000001", pattern)));
// 输出
字符串是否以136开头:false
#endregion
#region $
// 模式 $136
string pattern = @"$136";
Console.WriteLine(string.Format("字符串是否以136开头:{0}", Regex.IsMatch("13800010136", pattern)));
// 输出
字符串是否以136结束:true
#endregion
#region -
// 模式 ^[A-Za-z]+$
Regex regex = new Regex(@"^[A-Za-z]+$");
Console.WriteLine(string.Format("字符串是否全为英文字母:{0}",regex.IsMatch("Hello123")));
// 输出
字符串是否全为英文字母:false
#endregion
2、转义字符:将特殊字符变为普通的字符。下表列举了一些常用的转义字符:
字符 | 描述 |
---|---|
\a | 警报 |
\b | 退格 |
\e | Esc |
\f | 换页符 |
\n | 换行符 |
\r | 回车符 |
\t | 水平制表符 |
示例:
cs
#region \n
// 模式 \n(\w+) 匹配换行符+)");
string content = "\nHello\nWorld";
MatchCollection matches = Regex.Matches(content,@"\n(\w+)");
foreach (Match match in matches)
{
Console.WriteLine(string.Format("{0}",match.Value));
}
// 结果
Hello
World
#endregion
3、定位符:根据字符位置来进行匹配。下表列举一些常用的定位符:
字符 | 描述 |
---|---|
\A | 匹配字符串的开始位置 |
\Z | 匹配字符串的结尾位置或结尾换行之前的位置 |
\z | 匹配字符串的结尾位置 |
\G | 匹配上一个匹配结束的位置 |
\b | 匹配字符的开始或结束的位置 |
\B | 匹配字符的中间位置 |
示例:
cs
#region \A
// 模式 \A136
string pattern = @"\A136";
Console.WriteLine(string.Format("字符串是否以136开头:{0}", Regex.IsMatch("136SayHello", pattern)));
// 输出
字符串是否以136开头:true
#endregion
#region \B
// 模式 \Bin\w+
// \B 不在单词边界处开始匹配
// in 匹配子字符串"in"
// \w+ 匹配一个或多个单词字符
string content = "starting running ending";
foreach(Match match in Regex.Matches(content, @"\Bin\w+"))
{
Console.WriteLine(" {0} 在字符位置 {1}", match.Value, match.Index);
}
// 输出
ing 在字符位置 5
ing 在字符位置 13
#endregion
4、字符类:定义一组字符,其中的任一字符均可出现在输入字符串中以便成功匹配。
字符 | 描述 |
---|---|
[character_group] | 正字符组指定一个字符列表,任何一个字符可出现在输入字符串中以便进行匹配。 |
[first-last] | 正字符组一个字符范围 |
[^character_group] | 负字符组指定一个字符列表,任何字符不得出现在输入字符串中以便进行匹配。 |
[^first-last] | 负字符组一个字符范围 |
\w | 与任何单词字符匹配 |
\W | 任何非单词字符 |
\p{name} | 与 name 指定的 Unicode 通用类别或命名块中的任何单个字符匹配 |
\P{name} | 与不在 name 指定的 Unicode 通用类别或命名块中的任何单个字符匹配 |
\s | 与空白字符匹配 |
\S | 与任何非空白字符匹配 |
\d | 与任何十进制数字匹配 |
\D | 匹配不是十进制数的任意字符 |
示例:
cs
#region [first-last]
// 模式 \b[A-Z]\w*\b
// \b 在单词边界处开始。
// [A-Z] 匹配从 A 到 Z 的所有大写字符。
// \w* 匹配零个或多个单词字符。
// \b 与字边界匹配。
string content = "A work B Hard Zero Time";
foreach (Match match in Regex.Matches(content, @"\b[A-Z]\w*\b"))
{
Console.WriteLine("{0}", match.Value);
}
// 输出
A
B
Hard
Zero
Time
#endregion
#region \D
// 模式 ^\D\d{1,5}\D*$
// ^ 从输入字符串的开头部分开始匹配。
// \D 匹配非数字字符。
// \d{1,5} 匹配一到五个十进制数字。
// \D* 匹配零个、一个或多个非十进制字符。
// $ 匹配输入字符串的末尾部分。
string content = "A1039C";
Console.WriteLine("{0}", Regex.IsMatch(content, @"^\D\d{1,5}\D*$"));
// 输出
True
#endregion
5、限定符:指定输入中必须存在字符、组或字符类的多少实例才能找到匹配项。
字符 | 描述 |
---|---|
{n} | 恰好匹配 n 次 |
{n,} | 至少匹配 n 次 |
{n,m} | 匹配 n 到 m 次 |
*? | 匹配零次或多次 |
+? | 匹配一次或多次 |
?? | 匹配零次或一次 |
{n}? | 前面的元素恰好匹配 n 次 |
{n,?} | 前面的元素至少匹配 n 次,但次数尽可能少 |
{n,m}? | 匹配上一元素 n 次到 m 次,但次数尽可能少 |
示例:
cs
#region {n,m}
// 模式 ^\D\d{1,3}\D*$
// ^ 从输入字符串的开头部分开始匹配。
// \D 匹配非数字字符。
// \d{1,3} 匹配一到五个十进制数字。
// \D* 匹配零个、一个或多个非十进制字符。
// $ 匹配输入字符串的末尾部分。
string content = "B30590C";
Console.WriteLine("{0}", Regex.IsMatch(content, @"^\D\d{1,3}\D*$"));
// 输出
False
#endregion
6、分组
字符 | 描述 |
---|---|
(subexpression) | 捕获匹配的子表达式 |
(?<name>subexpression) | 捕获匹配的子表达式,并允许你按名称或编号访问它 |
(?<name1 -name2>subexpression) | 平衡组定义将删除以前定义的组和存储的定义 |
(?: subexpression) | 不会捕获与子表达式匹配的子字符串 |
(?imnsx-imnsx:subexpression) | 应用或禁用子表达式中指定的选项 |
(?= subexpression) | 定义零宽度正预测先行断言 |
(?! subexpression) | 定义零宽度负预测先行断言 |
(?> subexpression) | 定义零宽度正回顾后发断言 |
示例:
cs
#region (?> subexpression)
// 模式 (?<=\b31)\d{2}\b
// (?<=\b31) 以数字位数"31"开头,则继续匹配。
foreach (Match match in Regex.Matches("3124 2024 1140 3119", @"(?<=\b31)\d{2}\b"))
{
Console.WriteLine(match.Value);
}
// 结果
// 24
// 19
#endregion
#region (subexpression)
// 模式 (?<=\b31)\d{2}\b
// (?<=\b31) 以数字位数"31"开头,则继续匹配。
foreach (Match match in Regex.Matches("3124 2024 1140 3119", @"(?<=\b31)\d{2}\b"))
{
Console.WriteLine(match.Value);
}
// 结果
// 24
// 19
#endregion
7、替换
字符 | 描述 |
---|---|
$number | 替换按组 number 匹配的子字符串。 |
${name} | 包括替换字符串中由 (name) 指定的命名组所匹配的最后一个子字符串。 |
$$ | 包括替换字符串中的单个"$"文本 |
$& | 包括替换字符串中整个匹配项的副本。 |
$` | 包括替换字符串中的匹配项前的输入字符串的所有文本。 |
$' | 包括替换字符串中的匹配项后的输入字符串的所有文本。 |
$+ | 包括在替换字符串中捕获的最后一个组。 |
$_ | 包括替换字符串中的整个输入字符串。 |
小结
正则表达式是处理字符串的强大工具,拥有独特的语法和独立的处理引擎。本文通过一些示例来介绍正则表达式组成模式的常用字符及语法。