本章主要想和大家分享下正则表达式的一些基础用法,希望能够对一些小白有所帮助,也为了防止自己以后遗忘相关知识点,下面我们正式进入主题。 一、正则表达式 1、正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。 作用: 二、正则表达式的构成1、普通字符(如果直接写多个普通字符,则会被当做一个整体的字符串来匹配) 这包括所有的大小写字母字符,所有数字,所有标点符号以及一些特殊符号。 2、定义字符集(取值范围)(该点都是匹配单个字符,要想匹配字符串需要结合限定符来实现) ^ 代表非 3、组合字符(大写表示非)(该点都是匹配单个字符,要想匹配字符串需要结合限定符来实现) \d :匹配一个数字字符。等价于[0-9]。 4、特殊字符 $ :表示字符串的结尾位置(以什么结尾) 5、常用限定符 7、分组 当用()定义了一个正则表达式组后,正则引擎则会把被匹配的组按照顺序编号,存入缓存。 默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。 我们可以通过“\数字”的方式进行引用已经存入缓存的组。\1引用第一个匹配的组,\2引用第二个组,以此类推。 括号内的内容会被当成一个整体进行匹配。 8、非获取匹配和预查(零宽断言) 非获取匹配:是指正则引擎不会把被匹配的组存入缓存,我们也无法通过“\数字”的方式进行引用我们的组。 预查:预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。(即用来预查的表达式字符串不会被消耗,它只是用于指定一个位置) 零宽断言:用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言。 =========================================================================================== (?=exp)也叫零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。比如\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.时,它会匹配sing和danc。 (?<=exp)也叫零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp。比如(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading。 =========================================================================================== (?:pattern) 非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分时很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。 (?=pattern) 非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 (?!pattern) 非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。 (?<=pattern) 非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。 (?<!patte_n) 非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。 三、C#代码调用正则表达式命名空间 System.Text.RegularExpressions 1、new Regex(正则表达式).IsMatch(要匹配的字符串) 返回bool2、Regex.Match Match match = Regex.Match("age=30", @"^(.+)=(.+)$");if (match.Success) { Console.WriteLine(match.Groups[0].Value);//第0组 输出完整的字符串 age=30Console.WriteLine(match.Groups[1].Value);//第1组 ageConsole.WriteLine(match.Groups[2].Value);//第2组 30 }3、Regex.Matches StringBuilder sb = new StringBuilder(); sb.Append("<Name>张三</Name>\r\n<Name>李四</Name>\r\n<Name>王五</Name>"); MatchCollection mc = Regex.Matches(sb.ToString(), @"(?<=<Name>).*(?=</Name>)");foreach (Match m in mc) { Console.WriteLine(m.Value); } 四、示例说明接下来针对第二大点的内容我们举些例子来说明: 示例1(普通字符): 我们用 xyh 来匹配 xyh123 如下图所示: 从上面的正则表达式测试器匹配的结果可以看出:如果直接写多个普通字符,则会被当做一个整体的字符串来匹配。 示例2(元字符和限定符): 我们用 \d 来匹配 xyh123 如下图所示: 从匹配的结果可以发现\d只是匹配单个数字,所以有三个结果,分别为1、2、3,那如果想匹配一整个字符串123要怎么办呢?此时就要结合限定符来实现了。继续来看下下面的一张图。 从图中可以看出结合限定符后就可以实现匹配到123这个字符串了。 示例3(普通字符和元字符组合): 我们用 https://www\..+\.com 来匹配这么一句话:https://www.jd.com两个链接https://www.taobao.com 如下图所示: 可以发现匹配的结果为完整的一整句话,那为什么不是匹配出2个结果分别为 https://www.jd.com 和 https://www.taobao.com 呢? 那是因为默认情况下正则表达式采用贪婪模式匹配(即尽可能多匹配),所以匹配出了完整的一句话,此时可以用?来实现非贪婪模式匹配(即尽可能少匹配),如下图所示: 这样就匹配出了2个结果 示例4(分组): 我们用 (abc)\1 来匹配 abcabc666 如下图所示: 从图中可以看出匹配结果为abcabc,为什么会是这样呢?首先我们分组(abc)匹配到存入缓存中的值为abc,通过\1的方式就取到了存入缓存中的第1个分组值abc,这个分组值abc与原来分组(abc)匹配到的字符串abc组成新的匹配字符串abcabc,用新的匹配字符串abcabc去匹配abcabc666得到的匹配结果就是abcabc了。 示例5(非获取匹配): 非获取匹配(?:pattern)如下图所示: 从图中可以看出非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。因此无法通过“\数字”的方式来获取。 示例6(预查和零宽断言): 预查不消耗字符,它只是用于指定一个位置,如下图所示: 从图中可以看出用 ab(?=a) 来匹配 ababa123 时会得到两个结果而不是一个结果,那是因为预查不消耗字符(即不会消耗用来预查用的表达式exp对应的字符),它只是用于指定一个位置,所以在第3个位置的a(即第2个a)没有被消耗掉。当匹配到第1个结果ab后会从第3个位置的a(即第2个a)开始查找下一个能匹配的字符串,而不是从第4个位置的b(即第2个b)开始查找,这就解释了为什么会匹配到2个结果了。 PS:本文仅是个人见解 ,如有表述错误欢迎评论指正! 正则表达式测试器: 链接:https://pan.baidu.com/s/1CwyrLH2dwbBk1KVi2FCGDw 提取码:nwyc |
|