




已阅读5页,还剩11页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
.NET正则中的字符转义1概述这或许会是一个让人迷惑,甚至感到混乱的话题,但也正因为如此,才有了讨论的必要。在正则中,一些具有特殊意义的字符,或是字符序列,被称作元字符,如“?”表示被修饰的子表达式匹配0次或1次,“(?i)”表示忽略大小写的匹配模式等等。而当这些元字符被要求匹配其本身时,就要进行转义处理了。不同的语言或应用场景下,正则定义方式、元字符出现的位置不同,转义的方式也是林林总总,不一而同。2.NET正则中的字符转义2.1.NET正则中的转义符绝大多数语言中,“/”都被作为转义符,用来转义一些具有特殊意义的字符或字符序列,比如“/n”表示换行,“/t”表示水平制表符等。而这样的转义,应用到正则中,又会有一些意想不到的变化。话题由C#中一个正则问题引出string test =newstring/,/;Regexreg =newRegex(/$);foreach(stringsintest)richTextBox2.Text +=源字符串:+ s.PadRight(5, ) +匹配结果:+ reg.IsMatch(s) +/n;/*-输出-源字符串:/匹配结果:True源字符串:/匹配结果:False*/对于这个结果,或许有人会感到迷惑,字符串中的“/”不是代表一个经过转义的“/”字符吗?而“/”不就应该代表两个经过转义的“/”字符吗?那么上面正则匹配的结果应该是第一个为False,第二个为True才对啊?对于这一问题,直接解释或许不太容易理解,还是换种方式来解释吧。比如要匹配的字符是这样的stringtest =(;那么正则如何写呢?因为“(”在正则中是有特殊意义的,所以写正则时必须对它进行转义,也就是“/(”,而在字符串中,要使用“/”来表示“/”本身,也就是Regexreg =newRegex(/($);这个如果理解了,那再把“(”换回“/”,同样道理,在字符串中,要使用“/”来表示“/”本身,也就是Regexreg =newRegex(/$);通过这样的分析,可以看出,其实在以字符串形式声明的正则中,“/”匹配的实际上就是单独的一个“/”字符。总结一下它们之间的关系:输出到控制台或界面的字符串:/程序中声明的字符串:stringtest =/;程序中声明的正则:Regexreg =newRegex(/$);这样解释是不是已经可以理解了,那么是不是感觉这样很笨拙?是的,在程序中以字符串形式声明的正则,涉及到转义符时就是这样笨拙的。所以在C#中,还提供了另一种字符串声明方式,在字符串前加个“”,就可以忽略转义。string test =newstring /,/;Regexreg =newRegex(/$);foreach(stringsintest)richTextBox2.Text +=源字符串:+ s.PadRight(5, ) +匹配结果:+ reg.IsMatch(s) +/n;/*-输出-源字符串:/匹配结果:True源字符串:/匹配结果:False*/这样就简洁多了,也符合通常的理解。但同时也带来另一个问题,就是双引号的转义处理。在普通的字符串声明中,可以用“/”对双引号进行转义。stringtest =only a test;但是在字符串前加了“”后,“/”会被识别为“/”字符本身,这样就不能用“/”对双引号进行转义了,需要用“”对双引号进行转义。stringtest =only a test;而在VB.NET中,正则的定义只有一种形式,与C#中加了“”后的定义方式是一致的。DimtestAsString() =NewString() /,/DimregAsRegex =NewRegex(/$)ForEachsAsStringIntestRichTextBox2.Text +=源字符串:& s.PadRight(5, c) &匹配结果:& reg.IsMatch(s) & vbCrLfNext-输出-源字符串:/匹配结果:True源字符串:/匹配结果:False-2.2.NET正则中需要转义的元字符在MSDN中,以下字符作为正则中的元字符,在匹配其本身时,需要对其进行转义. $ ( | ) * + ? /但实际应用中,还要根据实际情况来判断,以上字符可能不需要转义,也可能不止以上字符需要转义。在正常的正则书写过程中,以上字符的转义通常都能被编写人员正常处理,但是在动态生成正则时,就需要格外的注意,否则变量中包含元字符时,动态生成的正则在编译时可能会抛异常。好在.NET中提供了Regex.Escape方法来处理这一问题。比如根据动态获取的id来提取相应的div标签内容。stringid =Regex.Escape(textBox1.Text);Regexreg =newRegex(?is)*(?*(?)|(?)|(?:(?!/?div/b).)*)* (?(o)(?!);如果不做转义处理,那么动态获取的id如果为“abc(def”这种形式,程序运行过程中就会抛出异常了。2.3.NET正则中字符组的转义在字符组中,元字符通常是不需要转义的,甚至于“”也是不需要转义的。stringtest =the test string:. $ ( | ) * + ? /;Regexreg =newRegex(.$(|)*+?/);MatchCollectionmc = reg.Matches(test);foreach(Matchminmc)richTextBox2.Text += m.Value +/n;/*-输出-.$(|)*+?/*/但是在正则书写时,字符组中的“”还是建议使用“/”对其转义的,正则本身就已经是非常抽象,可读性很低的了,如果在字符组中再掺杂进这样不经转义的“”,会使得可读性更差。而且在出现不正确的嵌套时,可能会导致正则编译异常,以下正则在编译时就会抛异常的。Regexreg =newRegex(.$(|)*+?/);然而,.NET的字符组中,是支持集合减法的,在这种正常语法形式下,是允许字符组嵌套的。stringtest =abcdefghijklmnopqrstuvwxyz;Regexreg =newRegex(a-z-aeiou+);MatchCollectionmc = reg.Matches(test);foreach(Matchminmc)richTextBox2.Text += m.Value +/n;/*-输出-bcdfghjklmnpqrstvwxyz*/这种用法可读性很差,应用也很少见,即使有这种需求也可以通过其它方式实现,了解一下即可,不必深究。话题再回到转义上,字符组中必须转义的只有“/”,而“”和“”出现在字符组中时,也是建议一定做转义处理的。另外有两个字符“”和“-”,出现在字符组中特定位置时,如果要匹配其本身,也是需要转义的。“”出现在字符组开始位置,表示排除型字符组,“Char”也就是匹配除字符组中包含的字符之外的任意一个字符,比如“0-9”表示除数字外的任意一个字符。所以在字符组中,要匹配“”字符本身,要么不放在字符组开始位置,要么用“/”进行转义。Regexreg1 =newRegex(0-9);Regexreg2 =newRegex(/0-9);这两种方式都表达匹配任意一个数字或普通字符“”。至于“-”在字符组中特殊性,举一个例子。stringtest =$;Regexreg =newRegex(#-*%&);richTextBox2.Text =匹配结果:+ reg.IsMatch(test);/*-输出-匹配结果:True*/正则表达式中明明没有“$”,为什么匹配结果会是“True”呢?支持用连字符“-”连接两个字符,来表示一个字符范围。需要注意的是,“-”前后的两个字符是有顺序的,在使用相同的编码时,后面的字符码位应大于或等于前面字符的码位。for(inti =#; i =*; i+)richTextBox2.Text += (char)i +/n;/*-输出-#$%&()*/由于“#”和“*”符合要求,“#-*”可以表示一个字符范围,其中就包含了字符“$”,所以上面的正则是可以匹配“$”的,如果只是把“-”当作一个普通字符处理,那么要么换个位置,要么把“-”转义。Regexreg1 =newRegex(#*%&-);Regexreg2 =newRegex(#/-*%&);这两种方式都表示匹配字符组中列举的字符中的任意一个。在字符组中,还有一个比较特殊的转义字符,“/b”出现在正则表达式中一般位置时,表示单词边界,也就是一侧为组成单词的字符,另一侧不是;而当“/b”出现在字符组中时,表示的是退格符,与普通字符串中出现的“/b”意义是一样的。同样的,还有一个容易被忽视,而且经常被忽视的转义符“|”,当“|”出现在正则表达式中一般位置时,表示左右两侧“或”的关系;而当“|”出现在字符组中时,它仅仅表示“|”字符本身,没有任何特殊意义,所以如果不是要匹配“|”本身,而试图在字符组中使用“|”时,是错误的。比如正则表达式“a|b”表示的是“a”、“b”、“|”中的任意一个,而不是“a”或“b”。2.4.NET正则应用中不可见字符转义处理对于一些不可见字符,要在字符串中表示时,需要用转义字符,比较常见的有“/r”、“/n”、“/t”等等,而这些字符在正则中应用,就变得有些神奇了,先看一段代码。stringtest =one line. /n another line.;List list =newList();list.Add(newRegex(/n);list.Add(newRegex(/n);list.Add(newRegex(/n);list.Add(newRegex(/n);foreach(Regexreginlist)richTextBox2.Text +=正则表达式:+ reg.ToString();MatchCollectionmc = reg.Matches(test);foreach(Matchminmc)richTextBox2.Text +=匹配内容:+ m.Value +匹配起始位置:+ m.Index +匹配长度:+ m.Length;richTextBox2.Text +=匹配总数:+ reg.Matches(test).Count +/n-/n;/*-输出-正则表达式:匹配内容:匹配起始位置:10匹配长度:1匹配总数:1-正则表达式:/n匹配内容:匹配起始位置:10匹配长度:1匹配总数:1-正则表达式:/n匹配内容:匹配起始位置:10匹配长度:1匹配总数:1-正则表达式:/n匹配总数:0-*/可以看到,前三种写法,输出的正则虽不同,但执行结果却是完全相同的,只有最后一种是没有匹配的。正则表达式一Regex(/n),其实就是以普通字符串形式来声明正则的,与用Regex(a)来匹配字符“a”是同样的道理,是不经过正则引擎转义的。正则表达式二Regex(/n),是以正则表达式形式来声明正则的,正如正则中的“/”就等同于字符串中的“/”一样,正则中的“/n”就等同于字符串中的“/n”,是经过正则引擎转义的。正则表达式三Regex(/n),与正则表达式二等价,是字符串前加“”的写法。正则表达式四Regex(/n),其实这个表示的是字符“/”后面跟一个字符“n”,是两个字符,这个在源字符串中自然是找不到匹配项的。这里需要特别注意的还是“/b”,不同的声明方式,“/b”的意义是不同的。stringtest =one line. /n another line.;List list =newList();list.Add(newRegex(line/b);list.Add(newRegex(line/b);list.Add(newRegex(line/b);list.Add(newRegex(line/b);foreach(Regexreginlist)richTextBox2.Text +=正则表达式:+ reg.ToString() +/n;MatchCollectionmc = reg.Matches(test);foreach(Matchminmc)richTextBox2.Text +=匹配内容:+ m.Value +匹配起始位置:+ m.Index +匹配长度:+ m.Length +/n;richTextBox2.Text +=匹配总数:+ reg.Matches(test).Count +/n-/n;/*-输出-正则表达式:line_匹配总数:0-正则表达式:line/b匹配内容:line匹配起始位置:4匹配长度:4匹配内容:line匹配起始位置:20匹配长度:4匹配总数:2-正则表达式:line/b匹配内容:line匹配起始位置:4匹配长度:4匹配内容:line匹配起始位置:20匹配长度:4匹配总数:2-正则表达式:line/b匹配总数:0-*/正则表达式一Regex(line/b),这里的“/b”是退格符,是不经过正则引擎转义的。源字符串中是没有的,所以匹配结果为0。正则表达式二Regex(line/b),是以正则表达式形式来声明正则的,这里的“/b”是单词边界,是经过正则引擎转义的。正则表达式三Regex(line/b),与正则表达式二等价,指单词边界。正则表达式四Regex(line/b),其实这个表示的是字符“/”后面跟一个字符“b”,是两个字符,这个在源字符串中自然是找不到匹配项的。2.5.NET正则应用中其它转义处理.NET正则应用中还有一些其它转义方式,虽然用得不多,但也顺便提一下吧。需求:把字符串中“”之间的数字前加上“$”stringtest =one test , another test ;Regexreg =newRegex();stringresult = reg.Replace(test,);richTextBox2.Text = result;/*-输出-one test , another test */也许你会惊奇的发现,替换结果不是在数字前加了“$”,而是将所有数字都替换为“$1”了。为什么会这样呢,这是因为在替换结构中,“$”是有特殊意义的,在它后面接数字,表示对对应编号捕获组匹配结果的引用,而有些情况下,需要在替换结果中出现“$”字符本身,但它后面又跟了数字,这时候就需要用“$”对它进行转义了。而上面这个例子却恰恰是由于这种转义效果导致出现了异常结果,要规避这一问题,可以使替换结果中不出现对捕获组的引用。stringtest =one test , another test ;Regexreg =newRegex(?=);stringresult = reg.Replace(test,$);richTextBox2.Text = result;/*-输出-one test , another test */3JavaScript及Java中的转义符JavaScript及Java中正则的转义符处理,以字符串形式声明时,基本上都是与.NET中一致的,简单的介绍一下。在JavaScript中,以字符串形式声明正则,与C#中的表现是一样的,同样会显得很笨拙。vardata = /,/;varreg =newRegExp(/$,);for(vari=0;id
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 点亮小灯泡讲课件
- 2024年建筑用天然石料项目投资申请报告代可行性研究报告
- 拐卖儿童的课件
- 中医馆简介讲课件
- 中医四诊法讲课件
- 抽样技术课程课件下载
- 全球化背景下的教育政策调整与实施
- 教育技术发展报告全球趋势与挑战
- 智慧安防系统保障城市安全的新举措
- 马鞍山学院《商务日语写作与会话》2023-2024学年第二学期期末试卷
- 医疗器械维修质量控制制度
- 2024-2030年中国连锁药店行业市场发展状况及投资前景规划研究报告
- 物流管理(全套课件)
- 第三章 基因工程(预测题)
- GB/T 14536.12-2024电自动控制器第12部分:能量调节器的特殊要求
- 门诊部医疗纠纷预防与处理
- 六年级语文下册 期末复习非连续性文本阅读专项训练(一)(含答案)(部编版)
- 美学原理学习通超星期末考试答案章节答案2024年
- 《实践论》(原文)毛泽东
- 电力分包项目合同范本
- 贵州省遵义市道德与法治中考试卷及答案指导(2025年)
评论
0/150
提交评论