c#正则表达式

参考:
https://blog.csdn.net/lxcnn?t=1
https://www.jianshu.com/p/8bf162425d83 (正向否定预查)
在线测试工具:
https://regex101.com/
http://c.runoob.com/front-end/854
https://tool.oschina.net/regex/

.Net正则类

限定符

"+":匹配一个或多个字符
"*":匹配零个或多个字符
"?":匹配零个或一个字符
{n}:匹配确定的n次
{n,}:至少匹配n次
{n,m}:最少匹配n次,最多匹配m次

定位符

"^":表示文本之首
"$":表示文本末尾
:匹配单词边界
B:匹配非单词边界

普通捕获组:(pattern)

匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到

            var reg = new Regex("(a)(b)\1\2");
            var isMatch = reg.IsMatch("abab");//true
            var matches = reg.Matches("abab");
            var count = matches[0].Groups;//3

命名捕获组(?pattern)

为捕获内容命名:(?pattern),等价于:?'name'pattern,只有.NET、PHP、Python等部分语言支持
引用捕获的文本:k

            var reg = new Regex("(?<name1>a)(?<name2>b)\k<name1>\k<name2>");
            var isMatch = reg.IsMatch("abab");//true
            var matches = reg.Matches("abab");
            var count = matches[0].Groups;//3

捕获组的引用

对捕获组的引用一般有以下几种:
1)正则表达式中,对前面捕获组捕获的内容进行引用,称为反向引用;
2)正则表达式中,(?(name)yes|no)的条件判断结构;
3)在程序中,对捕获组捕获内容的引用。

反向引用

普通捕获组反向引用:k,通常简写为 umber。例如:1、2、3...来表示第一、第二、第三组括号匹配的文本,在JScript中则使用$0…$9属性。
命名捕获组反向引用:k或者k'name'

            var reg = new Regex("(a)(b)\1\2");
            var isMatch = reg.IsMatch("abab");//true
            var matches = reg.Matches("abab");
            var count = matches[0].Groups;//3

条件判断结构

语法:

(?(Expression)yes|no)
(?(name)yes|no)

对于“(?(Expression)yes|no)”,它是“(?(?=Expression)yes|no)”的简写形式,相当于三元运算符
(?=Expression) ? yes : no
表示如果子表达式“(?=Expression)”匹配成功,则匹配“yes”子表达式,否则匹配“no”子表达式。如果“Expression”与可能出现的命名捕获组的组名相同,为避免混淆,可以采用“(?(?=Expression)yes|no)”方式显示声明“Expression”为子表达式,而不是捕获组名。
“(?=Expression)”验证当前位置右侧是否能够匹配“Expression”,属于顺序环视结构,是零宽度的,所以它只参与判断,即使匹配成功,也不会占有字符。

如果一对括号内包含另一对括号,则外层的括号先排序号。换句话说,哪一对的左括号 “(“ 在前,那这一对为先。

非捕获性分组(?:pattern)

它不会创建反向引用,反向引用会降低匹配速度,通过使用非捕获性分组无需存储结果的开销。创建非捕获性分组:(?:d+),这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。

            var reg = new Regex("(?:a)(b)\1");
            var isMatch = reg.IsMatch("abb");//true
            var matches = reg.Matches("abb");
            var count = matches[0].Groups;//2

正向肯定预查(?=pattern)

当某个特定的字符分组出现在另一个字符串之前时才去匹配它。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,
“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

            var reg = new Regex("windows(?=95|98|xp)");
            var isMatch = reg.IsMatch("windows98,windowsxp,windows2000");//true
            var matches = reg.Matches("windows98,windowsxp,windows2000");//windows、windows

反向肯定预查(?<=pattern)

反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows"能匹配"2000Windows"中的"Windows",但不能匹配"3.1Windows"中的"Windows"。

正向否定预查(?!pattern)

与正向前瞻的区别是当特定字符不出现在另一字符前才去匹配它。这是一个非获取匹配。

案例1

“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符。

            var reg = new Regex("windows(?!95|98|xp)");
            var isMatch = reg.IsMatch("windows98,windowsxp,windows2000");//true
            var matches = reg.Matches("windows98,windowsxp,windows2000");//windows

案例2

匹配以x开头, 后面不包含-, 的字符串. 写法如下:

^x((?!-).)*$

后面的((?!-).)*是什么意思呢?
x(?!-)意思就是x的后面没有:, 那么如果这么说的话, 他应该可以成功匹配形如xy, xx等字符串了? 并不是的. 注意上文维基百科解释中的最后一句话, 预查不消耗字符, 也就是说(?!-)只是表达了后面不能跟:, 但是并不代表xy中的y, 所以正确的表达式是形如x(?!-).x(?!-)w这种, 让.w来代表xy中的y,如下:
x123 :成功匹配
x123- :匹配失败

案例3

验证字符串中任意位置出现的连续四个数字在整个字符串中是否有重复,有重复为True,无重复为False

string[] test = new string[] { "1985aaa1985bb", "bcae1958aaa1955fef", "atijc1944cvkd", "df2564isdjfef2564d" };
Regex reg = new Regex(@"(d{4})(?:(?!1).)*1");
foreach (string s in test)
{
      richTextBox2.Text += "源字符串:  " + s.PadRight(25, ' ') + "验证结果:  " + reg.IsMatch(s) + "
";
}
/*--------输出--------
源字符串:  1985aaa1985bb            验证结果:  True
源字符串:  bcae1958aaa1955fef   验证结果:  False
源字符串:  atijc1944cvkd            验证结果:  False
源字符串:  df2564isdjfef2564d       验证结果:  True
*/

反向否定预查(?<!pattern)

反向否定预查,与正向否定预查类似,只是方向相反。例如"(?<!95|98|NT|2000)Windows"能匹配"3.1Windows"中的"Windows",但不能匹配"2000Windows"中的"Windows"。

ASCII、Unicode表示字符

除了可以用字符来表示它们本身,也可以使用它们的ASCII代码或者Unicode代码指定字符。要使用ASCII来表示一个字符,则必须指定一个两位的十六进制数或八进制数,十六进制在前面加上x,八进制在前加。例如:字符b的ASCII码为98,等于十六进制的62,因此表示b可以使用x62。如果要使用Unicode来表示字符,必须指定字符串的四位的十六进制形式。因此b应该是u0062。

[u4e00-u9fa5]:匹配任意一个中文字符

RegexOptions

IgnoreCase:忽略大小写

Multiline:多行模式

使边界字符 ^ 和 $ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾。
Multiline模式下,^ 也匹配 ' ' 或 ' ' 之后的位置;$ 也匹配 ' ' 或 ' ' 之前的位置。

            var reg = new Regex("^[a-zA-Z]+$", RegexOptions.Multiline);
            var matches = reg.Matches("abc
def");
            var count = matches.Count;//2

Singleline:单行模式

            var reg = new Regex("^[a-zA-Z]+$", RegexOptions.Singleline);
            var matches = reg.Matches("abc
def");
            var count = matches.Count;//0
原文地址:https://www.cnblogs.com/fanfan-90/p/14670115.html