正则表达式进阶内容,零宽断言、捕获分组、正则提取、正则替换、正则匹配规则、贪婪正则、非贪婪正则

常规正则别人写的很多了,这里是个人对于零宽系列进行理解,很多人看别人描述介绍到头来也不知道这玩意怎么用,是干什么的。

零宽断言

以下举个例子:使用正则判断一个字符串是否符合以下要求
1、该字符串包含45
2、45前面不能是3
3、45后面必须是6
4、6必须是最后一个字符
正则:(?<!3)45(?=6)6$
不在意2和3的条件,正则就是:456$
区别就是多了(?<!)和(?=)

xx字符的前面(后面)必须(不能)是xx字符,这就是零宽断言的作用
零宽正则诸如(?=xxx),需要理解为修饰符,在常规正则的基础上进行修饰,使正则表达式具有更多功能

什么算修饰符呢,请看代码:

/**
* 4种零宽断言
* a(?!xxxx):a右边如果不是xxxx则为true  //对左进行修饰
* a(?=xxxx):a右边如果是xxxx则为true    //对左进行修饰
* (?<!xxxx)a:a左边如果不是xxxx则为true //对右进行修饰
* (?<=xxxx)a:a左边如果是xxxx则为true   //对右进行修饰
* 
* 由于零宽断言属于修饰,所以不会被Group提取到
*/

//常规匹配,1开头s结尾,中间是23.min.j的字符串
Console.WriteLine(Regex.IsMatch("123.min.js", @"^123\.min\.js$"));//true

//对上面正则使用零宽正则进行修饰(限制),在上面正则基础上增加零宽正则即可
//在123的后面加了(?<!111),表示.min.js前不可能是111
Console.WriteLine(Regex.IsMatch("123.min.js", @"^123(?<!111)\.min\.js$"));//true
Console.WriteLine(Regex.IsMatch("111.min.js", @"(?<!111)\.min\.js$"));//false,因为.min.js前面跟着的是111

//表示123后面加了(?!111),表示123后面不可能跟着111,区别就在于<符号。
//<符号表示对后面的字符(.min.js)进行修饰,不加就对前面的字符(123)进行修饰
Console.WriteLine(Regex.IsMatch("123.min.js", @"^123(?!111)\.min\.js$"));//true
Console.WriteLine(Regex.IsMatch("123111.min.js", @"^123(?!111)111\.min\.js$"));//false
Console.WriteLine(Regex.IsMatch("12311.min.js", @"^123(?!111)11\.min\.js$"));//true,因为123后面跟着的是11不是111

//表示23.后面必须跟着的是min,不然false
Console.WriteLine(Regex.IsMatch("123.min.js", @"23\.(?=min)"));//true,23.后面跟着的就是min
Console.WriteLine(Regex.IsMatch("123.mn.js", @"23\.(?=min)"));//false,23.后面跟着的是mn而不是min
Console.WriteLine(Regex.IsMatch("123.mn.js", @"23\."));//true,包含23.,没做任何限制
Console.WriteLine(Regex.IsMatch("123.mn.js", @"23\.(?<=min)"));//false,做了限制,但是由于<符号,修饰对象是右边的 ""空字符串,表示 空字符串前必须是min
Console.WriteLine(Regex.IsMatch("123.min", @"(?<=min)"));//true,因为min右边的空字符串前的字符确实是min

捕获,分组,正则提取

不多说,直接看代码

//正常正则提取文字,如下,提取1开头,0结尾中间的所有字符
GroupCollection res = Regex.Match("1234567890", @"^1(.*)0$").Groups;
Console.WriteLine(res[1]);

//只要在()内改为(?'自定义组名'),提取时候就可以用组名提取,遇到复杂的嵌套提取时非常好用
GroupCollection res2 = Regex.Match("1234567890", @"^1(?'组名1'.*)0$").Groups;
Console.WriteLine(res2["组名1"]);

正则替换

//将匹配到的abc替换为xxabcxx,
//${1}表示被()起来的第一个
//如果()写为(?'组号1'),也可用${组号1}
Console.WriteLine(Regex.Replace("123abc456", @"(abc)", "xx${1}xx"));//结果:123xxabcxx456,以下2条同理
Console.WriteLine(Regex.Replace("123abc456", @"(?'组号1'abc)", "xx${组号1}xx"));
//写法2,不用()括起来,将所有匹配到的字符执行自定义规则,比如去空
//n => 后面的表达式可以写为 {
//  xxxx;//代码块
//  return xx;
//}
Console.WriteLine(Regex.Replace("123abc 456", @"abc ", n => "xx" + n.ToString().Trim() + "xx"));

//$+表示将匹配到的abc456替换为组里最后一个(也就是5)
Console.WriteLine(Regex.Replace("123abc456", @"(abc).*(.)6", "xx$+xx"));//结果:123xx5xx

//$_表示将匹配到的abc用整个字符串(123abc456)进行替换
Console.WriteLine(Regex.Replace("123abc456", @"abc", "$_"));//结果:123123abc456456

//$`表示将匹配到的abc替换为abc前面的所有字符
Console.WriteLine(Regex.Replace("123abc456", @"abc", "$`啊"));//结果:123123啊456

//$'表示将匹配到的abc替换为abc后面的所有字符
Console.WriteLine(Regex.Replace("123abc456", @"abc", "$'啊"));//结果:123456啊456

//单独$不表示任何意思
Console.WriteLine(Regex.Replace("123abc456", @"abc", @"$"));//结果:123$456

//如果要把字符替换为刚好是 $_ $`之类的怎么办呢,老老实实用string.Replace吧

正则规则(RegexOptions枚举)

枚举RegexOptions:
常用:
IgnoreCase表示不区分输入的大小写
Singleline表示单行模式,改变元字符.的意义,它可以匹配换行符
Multiline表示多行模式,改变元字符 ^ 和$的含义,它们可以匹配行的开头和结尾
ExplicitCapture表示只保存显式命名的组
RightToLeft表示从右向左扫描、匹配,这时,静态的Match方法返回从右向左的第一个匹配
不常用:
Complied表示编译此模式
CultureInvariant表示不考虑文化背景
ECMAScript表示符合ECMAScript,这个值只能和IgnoreCase、Multiline、Complied连用
IgnorePatternWhitespace表示去掉模式中的非转义空白,并启用由#标记的注释
None表示无设置,此枚举项没有意义
注意:Multiline在没有ECMAScript的情况下,可以和Singleline连用。Singleline和Multiline不互斥,但是和ECMAScript互斥。

使用:Regex.IsMatch(“字符”,“正则”,RegexOptions.IgnoreCase),一般正则使用函数的后面都能加

贪婪正则、非贪婪正则

//一般程序中默认为贪婪正则,能多匹配就多匹配,有些语言可以修改正则模式
Console.WriteLine(Regex.Match("<a xx>abc</a>", "(<.*>)").Groups[1]);//结果<a xx>abc</a>
// *后加个?就变成非贪婪正则,能少匹配就少匹配
Console.WriteLine(Regex.Match("<a xx>abc</a>", "(<.*?>)").Groups[1]);//结果<a xx>

其他

提取多个符合要求的字符

string str = "<abc>7777<123>";
var res = Regex.Match(str, "^.*(<.*?>).*$").Groups;
foreach (var item in res) {
    /**
     * 会出现2个值,第一个为 匹配 到的值,即Group[0],第二个为用() 捕获 到的值即Group[1]
     * 匹配到2个,第一个为Group[0]表示正则匹配到的值
     * 第二个Group[1]表示捕获(()符号)到的第一个值:<abc>
     * 不使用()捕获而去获取Group[1],不会发生数组越界,只能获取到空字符串
     */
    Console.WriteLine(item);
}
//没有匹配到<123>,想匹配所有符合规则的,需要使用Matches
var res2 = Regex.Matches(str, "<.*?>");//Matches无视(),不需要加
foreach (var item in res2) {
    Console.WriteLine(item.ToString());//匹配到2个,第一个<abc>,第二个<123>,都正常获取
}

(?:xxx)的作用以及@在正则表达式中的作用

/**
 * C#中正则表达式前一定要加@符号,否则遇见需要\转义会很头疼
 * (?:xx)表示捕获时,忽略这里的捕获
 */
Console.WriteLine(Regex.Match("<123>abc<456>", @"^(<.*?>).*(<.*?>)$").Groups[1]);//<123>
Console.WriteLine(Regex.Match("<123>abc<456>", @"^(?:<.*?>).*(<.*?>)$").Groups[1]);//<456>

正则转义,用于正则表达式内传参

/// <summary>
/// 当你需要对变量进行正则替换,匹配等操作时,请将正则特殊字符转义掉,以防正则出错
/// </summary>
private static string 字符串转义(string str) {
    return Regex.Replace(str, @"(\\|\?|\*|\^|\$|\+|\(|\)|\||{|\[)", n => $@"\{n}");
}

常用符号\d,\s等基础正则符号介绍
正则表达式手册

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值