正则表达式分组相关的知识
来源:百度文库 编辑:神马文学网 时间:2024/04/28 02:14:10
一、组的分类
正则中的组有捕获组和非捕获组,而捕获组又分为普通的捕获组和命名捕获组,分别为
捕获组:(exp)
命名捕获组:(?exp)
非捕获组:(?:exp)
二、组的作用
1、捕获组的作用
捕获组的作用是将正则表达式exp匹配到的内容保存到组里,供以后使用
比如这样一个字符串:
CSDN
我想得到网址,而它符合的规则是在标签内,那就可以这样做
上面的正则表达式匹配到了,而我们想得到网址,表达式其它部分只是为了保证取到的网址是在标签内的,所以这里用到的捕获组,把匹配到的网址保存到捕获组里,然后用m.Groups[1].Value得到这个捕获组所匹配到的内容
m.Groups[1].Value是一种对捕获的引用方式,还有另外一种引用方式m.Result("$1"),效果是一样的
普通捕获组是用1,2,3...这样的自然数对捕获组进行引用的
而命名捕获组可以不用去数捕获组的序号,直接通过捕获组的命称对它进行引用
至于捕获组的分组命名及序号排序规则,在后面说明
2、非捕获组的作用
非捕获组的作用有两个,第一个比较常用,第二个了解一下即可
(1)、节省系统资源,提高效率
在使用“|”表示“或”的关系时,稍微复杂的情况,需要用()来限制“|”的作用范围,否则即表示“|”的左右两侧整体为“或”的关系,这是题外话,这里不详细说明了,还有用{num}来表达式匹配次数时,有时前面也要用到()限制作用范围
而使用()来限制作用范围的同时,默认情况下会把匹配到的结果保存到一个捕获组里,而大多数时候,我们是不需要保存这部分内容的,这就带来一定的副作用,浪费了系统资源,降低了效率
非捕获组的一个作用就是用来消除这种副作用的,(?:exp)用来匹配exp所表示的规则,但不将匹配结果保存到捕获组里
比如匹配HH:mm:ss这样的时间
(?:[01][0-9]|2[0-3])验证小时部分是否符合规则,但不会将匹配结果保存到捕获组里
(?::[0-5][0-9]){2}验证了分秒部分,但不会将匹配结果保存到捕获组里
(2)、在使用Regex.Split方法时,起到与RegexOptions .ExplicitCapture参数相同的作用,这个用得不多,了解一下就行了
三、捕获组分组命名及序号排序
普通捕获组是按“(”从左到右出现的先后顺序以自然数1,2,3...进行命名的
命名捕获组就是以(?exp)中的name进行命名的
但是要注意一点,在表达式匹配成功的前提下,$0在任何情况下都表示整个表达式所匹配到的内容,m.Groups[0].Value表示整个表达式匹配到的内容,可以简写为m.Value
另外就是命名捕获组除了可以用name对它进行引用外,还可以通过序号对它引用,它的命名规则为:先对普通捕获组从左到右进行序号命名,然后再从开头,从左到右对命名捕获组进行序号命名,举例如下
[^"]*)"\s*title="([^"]*)"[^>]*>(?[\s\S]*?)
2 url 1 3 text
四、组的另一种引用方式
除了上面 m.Groups[1].Value 和 m.Result("$1") 这两种对结果集进行处理时的引用方式外,还有在替换时的一种引用方式,举例如下
只保留网址和链接文字,去掉标签中其它无用信息
普通捕获组就是用$number来引用,而命名捕获是用${name}来引用
预搜索
(?=exp)
(?!exp)
(?<=exp)
(?
下面的说明很容易让人头晕,不看也罢,我将以另一种方式对它们的作用和用法进行说明
(?=exp) 匹配exp前面的位置
(? <=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?
有的资料上翻译为零宽度断言,我习惯于预搜索这种叫法,前两个为正向预搜索,后两个为反向预搜索,当然还有其它翻译,其实都是一个意思,知道就行,不必在意
这四种表达式,它们与非捕获的相同之处在于,并不将匹配到的结果保存到捕获组,不同之处在于,非捕获组匹配到的内容,虽然不保存到捕获组,但却是在结果$0实实在在存在的,而以上四种表达式所匹配到的内容,一般来说,是不存在$0内的,所以说它们匹配的结果是零宽度的
更好的理解方式,是把它们作为附加条件,而不是正则表达式的组成部分
为了更好的说明,先说一下“缝隙”的概念,“缝隙”是零宽度的,它只是字符串中的一个位置,而不是实际的字符,如字符串“ab”,在“a”前面,“a”和“b”中间,还有“b”后面,分别有一个“缝隙”,也就是整个字符串有三个“缝隙”
(?=exp) 在所在“缝隙”的后面附加一个条件,也就是“缝隙”后面必须能够匹配exp的内容
(?!exp) 在所在“缝隙”的后面附加一个条件,也就是“缝隙”后面必须不能够匹配exp的内容
(?<=exp) 在所在“缝隙”的前面附加一个条件,也就是“缝隙”前面必须能够匹配exp的内容
(?
举例说明如下:
<[^>]*>表达式任意html标签
附加一个条件
<(?!img)[^>]*>
这个就表示除标签外的所有标签,看下实际例子
输出结果为:
这时再看一下<(?!img)[^>]*>这个正则表达式
(?!img)所在的“缝隙”是“<”和它后面的第一个字符之间的“缝隙”,它表示的意思就是,在这个“缝隙”的后面,不能是img,整个表达式的意思也就是不匹配标签
同理,<(?=img)[^>]*>表示只匹配标签
输出:
(?<=]*>)]*>表示只匹配前面为标签的标签
输出:
(?]*>)]*>表示只匹配前面不为标签的标签
输出:
以上面的这个(?<=]*>)]*>为例,表达式中虽然有(?<=]*>),但是在结果m.Value中并不存在它匹配到的内容,所以说它是零宽度的,只是作为一个附加条件存在
正则中的组有捕获组和非捕获组,而捕获组又分为普通的捕获组和命名捕获组,分别为
捕获组:(exp)
命名捕获组:(?
非捕获组:(?:exp)
二、组的作用
1、捕获组的作用
捕获组的作用是将正则表达式exp匹配到的内容保存到组里,供以后使用
比如这样一个字符串:
CSDN
我想得到网址,而它符合的规则是在
- C# code
string test = "CSDN";Match m = Regex.Match(test, @"]*>", RegexOptions.IgnoreCase);if (m.Success)MessageBox.Show(m.Groups[1].Value);
上面的正则表达式匹配到了,而我们想得到网址,表达式其它部分只是为了保证取到的网址是在
m.Groups[1].Value是一种对捕获的引用方式,还有另外一种引用方式m.Result("$1"),效果是一样的
普通捕获组是用1,2,3...这样的自然数对捕获组进行引用的
而命名捕获组可以不用去数捕获组的序号,直接通过捕获组的命称对它进行引用
- C# code
string test = "CSDN";Match m = Regex.Match(test, @"[^""]*)""[^>]*>", RegexOptions.IgnoreCase);if (m.Success)MessageBox.Show(m.Groups["url"].Value);
至于捕获组的分组命名及序号排序规则,在后面说明
2、非捕获组的作用
非捕获组的作用有两个,第一个比较常用,第二个了解一下即可
(1)、节省系统资源,提高效率
在使用“|”表示“或”的关系时,稍微复杂的情况,需要用()来限制“|”的作用范围,否则即表示“|”的左右两侧整体为“或”的关系,这是题外话,这里不详细说明了,还有用{num}来表达式匹配次数时,有时前面也要用到()限制作用范围
而使用()来限制作用范围的同时,默认情况下会把匹配到的结果保存到一个捕获组里,而大多数时候,我们是不需要保存这部分内容的,这就带来一定的副作用,浪费了系统资源,降低了效率
非捕获组的一个作用就是用来消除这种副作用的,(?:exp)用来匹配exp所表示的规则,但不将匹配结果保存到捕获组里
比如匹配HH:mm:ss这样的时间
- C# code
MessageBox.Show(Regex.IsMatch("18:23:55", "^(?:[01][0-9]|2[0-3])(?::[0-5][0-9]){2}$").ToString());
(?:[01][0-9]|2[0-3])验证小时部分是否符合规则,但不会将匹配结果保存到捕获组里
(?::[0-5][0-9]){2}验证了分秒部分,但不会将匹配结果保存到捕获组里
(2)、在使用Regex.Split方法时,起到与RegexOptions .ExplicitCapture参数相同的作用,这个用得不多,了解一下就行了
三、捕获组分组命名及序号排序
普通捕获组是按“(”从左到右出现的先后顺序以自然数1,2,3...进行命名的
命名捕获组就是以(?
但是要注意一点,在表达式匹配成功的前提下,$0在任何情况下都表示整个表达式所匹配到的内容,m.Groups[0].Value表示整个表达式匹配到的内容,可以简写为m.Value
另外就是命名捕获组除了可以用name对它进行引用外,还可以通过序号对它引用,它的命名规则为:先对普通捕获组从左到右进行序号命名,然后再从开头,从左到右对命名捕获组进行序号命名,举例如下
[^"]*)"\s*title="([^"]*)"[^>]*>(?
2 url 1 3 text
- C# code
string test = "CSDN";Match m = Regex.Match(test, @"[^""]*)""\s*title=""([^""]*)""[^>]*>(?
[\s\S]*?) ", RegexOptions.IgnoreCase);if (m.Success){richTextBox1.Text += m.Groups[0].Value + "\n"; //CSDN richTextBox1.Text += m.Groups[1].Value + "\n"; //床上等你 richTextBox1.Text += m.Groups[2].Value + "\n"; //http://bbs.csdn.net richTextBox1.Text += m.Groups["url"].Value + "\n"; //http://bbs.csdn.net richTextBox1.Text += m.Groups[3].Value + "\n"; //CSDN richTextBox1.Text += m.Groups["text"].Value + "\n"; //CSDN}
四、组的另一种引用方式
除了上面 m.Groups[1].Value 和 m.Result("$1") 这两种对结果集进行处理时的引用方式外,还有在替换时的一种引用方式,举例如下
只保留网址和链接文字,去掉
- C# code
string test = "CSDN";string result = Regex.Replace(test, @"]*>(?
[\s\S]*?) ", @"${text}", RegexOptions.IgnoreCase);MessageBox.Show(result);
普通捕获组就是用$number来引用,而命名捕获是用${name}来引用
预搜索
(?=exp)
(?!exp)
(?<=exp)
(?
下面的说明很容易让人头晕,不看也罢,我将以另一种方式对它们的作用和用法进行说明
(?=exp) 匹配exp前面的位置
(? <=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?
有的资料上翻译为零宽度断言,我习惯于预搜索这种叫法,前两个为正向预搜索,后两个为反向预搜索,当然还有其它翻译,其实都是一个意思,知道就行,不必在意
这四种表达式,它们与非捕获的相同之处在于,并不将匹配到的结果保存到捕获组,不同之处在于,非捕获组匹配到的内容,虽然不保存到捕获组,但却是在结果$0实实在在存在的,而以上四种表达式所匹配到的内容,一般来说,是不存在$0内的,所以说它们匹配的结果是零宽度的
更好的理解方式,是把它们作为附加条件,而不是正则表达式的组成部分
为了更好的说明,先说一下“缝隙”的概念,“缝隙”是零宽度的,它只是字符串中的一个位置,而不是实际的字符,如字符串“ab”,在“a”前面,“a”和“b”中间,还有“b”后面,分别有一个“缝隙”,也就是整个字符串有三个“缝隙”
(?=exp) 在所在“缝隙”的后面附加一个条件,也就是“缝隙”后面必须能够匹配exp的内容
(?!exp) 在所在“缝隙”的后面附加一个条件,也就是“缝隙”后面必须不能够匹配exp的内容
(?<=exp) 在所在“缝隙”的前面附加一个条件,也就是“缝隙”前面必须能够匹配exp的内容
(?
举例说明如下:
<[^>]*>表达式任意html标签
附加一个条件
<(?!img)[^>]*>
这个就表示除
- C# code
string test = "";MatchCollection mc = Regex.Matches(test, @"<(?!img)[^>]*>", RegexOptions .IgnoreCase);foreach(Match m in mc){richTextBox1.Text += m.Value + "\n";}
输出结果为:
这时再看一下<(?!img)[^>]*>这个正则表达式
(?!img)所在的“缝隙”是“<”和它后面的第一个字符之间的“缝隙”,它表示的意思就是,在这个“缝隙”的后面,不能是img,整个表达式的意思也就是不匹配
同理,<(?=img)[^>]*>表示只匹配
- C# code
string test = "";MatchCollection mc = Regex.Matches(test, @"<(?=img)[^>]*>", RegexOptions.IgnoreCase);foreach(Match m in mc){MessageBox.Show(m.Value);}
输出:
(?<=]*>)]*>表示只匹配前面为
- C# code
string test = "";MatchCollection mc = Regex.Matches(test, @"(?<=]*>)]*>", RegexOptions.IgnoreCase);foreach(Match m in mc){MessageBox.Show(m.Value);}
输出:
(?]*>)]*>表示只匹配前面不为
- C# code
string test = "";MatchCollection mc = Regex.Matches(test, @"(?]*>)]*>", RegexOptions.IgnoreCase);foreach(Match m in mc){MessageBox.Show(m.Value);}
输出:
以上面的这个(?<=]*>)]*>为例,表达式中虽然有(?<=]*>),但是在结果m.Value中并不存在它匹配到的内容,所以说它是零宽度的,只是作为一个附加条件存在
正则表达式分组相关的知识
【正则表达式专题】正则表达式的应用
JS的正则表达式
常用的正则表达式
正则表达式--递归匹配、非贪婪匹配与分组替换
Java正则表达式的总结
java 正则表达式的使用
一些常用的正则表达式
Extjs 正则表达式的判断
常用的一些正则表达式
正则表达式
正则表达式
正则表达式
正则表达式
正则表达式
正则表达式:正则表达式基础
正则表达式的五个成功习惯
[ 永远的UNIX > Java正则表达式详解 ]
处理正则表达式的java包:regexp
常用的匹配正则表达式和实例
揭开正则表达式的神秘面纱
正则表达式的五个成功习惯
正则表达式的用法(下)
常用的JavaScript验证正则表达式