正则的力量无法小觑,短短的几个字符,往往胜过几十行的代码,大大可以简化我们冗余的代码。

以前在js里用正则比较多,今天来熟悉下C#中正则的使用方法,权当笔记了!

如果把正则当做一门语言的话,那么正则的学习也和其他语言一样,从历史渊源到基本语法,从高级特性到性能优化,正则一样不少。

历史:

 正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。   1956 年, 一位叫 Stephen Kleene 的数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为“神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式,因此采用“正则表达式”这个术语。   随后,发现可以将这一工作应用于使用 Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson 是 Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的 qed 编辑器。   如他们所说,剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。

基本语法字符:

\d   (代表0-9的数字)

\D   (代表除数字以外的其他字符)

\w   (代表所有的单词字符-数字、字母、下划线)

\W   (代表所有除单词字符外的字符)

\s     (代表空白字符)

\S    (代表除了空白字符以外的字符)

.       (除了换行符外的任意字符)

[,,,]  (匹配方括号内列出的所有字符)

[^,,,] (匹配方括号内列出的字符外的所有字符)

\b     (匹配单词边界)

\B     (匹配非单词边界)

^      (匹配字符开头位置)

$      (匹配字符结尾位置)

{n}   (匹配n个符合条件的字符)

{n,m} (匹配n到m个符合条件的字符)

{n,}    (匹配大于等于n个符合条件的字符)

?       (匹配1次或0次符合条件的字符)

+       (匹配一次或多次符合条件的字符)

*        (匹配0次或多次符合条件的字符)

(a|b)   (匹配符合a条件或者b条件的字符)

下面练习一些基本的例子来熟悉上面的基本语法

1.匹配3个数字,例如134

\d{3}

2.匹配一个单词以字母开头字母结尾中间是一个或多个数字,例如a123b

^[a-zA-Z]\d+[a-zA-Z]$

3.匹配固定电话  例如 021-81234563  或者 0512-81755456

^\d{3,4}-\d{8}

4.匹配正整数

[1-9][0-9]*

5.匹配两位小数

(([0-9][1-9]*)|([1-9][0-9]*))+\.\d{2}

6.匹配邮政编码

^\d{6}$

7.匹配手机号码

^[1][3-9]\d{9}$

8.匹配身份证号码

^\d{18}$)|^\d{15}$

9.匹配汉字

^[\u4e00-\u9fa5]{1,}$

10.匹配URL

^http(s)?([\w-]+\.)+(\w-)+(/[\w-./?%&=]*)?$

上述是基本的使用语法,让我们来看看C#中是如何使用它们的

System.Text.RegularExpressions.Regex  这个事C#正则的使用类

他提供了如下方法来使用正则

1.IsMatch 是否匹配-示例代码:

 //验证手机号码
public bool IsMobile(string mobile) {
return System.Text.RegularExpressions.Regex.IsMatch(mobile, @"^[1][3-9]\d{9}$");
}

2.Split 根据条件切割字符串

示例代码

//根据数字拆分字符串
public String[] SplitStr(String str) {
return System.Text.RegularExpressions.Regex.Split(str, @"[0-9]");
} protected void btn_split_Click(object sender, EventArgs e) {
string[] Result = SplitStr(this.tb_pwd.Text);
int Len = Result.Length;
for (int i = ; i < Len; i++) {
if (Result[i] != "") {
Response.Write("<script>alert('拆分为!" + Result[i] + "')</script>");
}
}
}

3.Replace

替换字符串

     //替换字符串中的所有数字为指定字符
public String ReplaceWord(string str1, string str2) {
return System.Text.RegularExpressions.Regex.Replace(str1, @"\d", str2);
}

4.Matches

获取匹配集合

 //验证重复出现的词(正则需要优化)
public String[] RepeatWords(string str) {
System.Text.RegularExpressions.MatchCollection matches =
System.Text.RegularExpressions.Regex.Matches(str, @"\b(?<word>\w+)\s+(\k<word>)\b", System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.IgnoreCase);
int AIndex = matches.Count;
if (AIndex != ) {
String[] RepeatWord = new string[AIndex];
int i=;
foreach (System.Text.RegularExpressions.Match match in matches) {
string word = match.Groups["word"].Value;
RepeatWord[i] = word;
i++;
}
return RepeatWord;
}
else {
return null;
}
}

正则的高级特性

1.分组和非捕获性分组

组是把符合括弧中组条件的字符保存起来,通过索引的方法供下面的匹配的调用

例如 需要匹配  abc123abc

我们可以这样^(abc)123\1$,这里的()即是一个需要捕获的组,他的条件是abc,这个时候在下一个位置,我们只要通过\1就可以重复利用上一次捕获过的值来匹配,如果有两个分组,那我们获取第二个分组就用\2

那在C#中如何利用呢?

string  x = "abc123abc";
Regex r = new Regex(@"^(abc)123\1$");
if (r.IsMatch(x))
{
Console.WriteLine("group1 value:" + r.Match(x).Groups[].Value);//输出:abc
}

这里为何是Groups[1]呢 因为在匹配的时候第一个匹配的是符合所有条件的字符串,然后存储符合条件的组

我们也可以为组命名:

string  x = "abc123abc";
Regex r = new Regex(@"^(?<test>abc)123\1$");
if (r.IsMatch(x))
{
Console.WriteLine("group1 value:" + r.Match(x).Groups["test"].Value);//输出:abc
}

这样是不是就更加形象了呢

有的时候我们想匹配组但是不想保存这个组匹配的内容,这个时候我们可以使用?:

 string  x = "abc123abc";
Regex r = new Regex(@"^(?:abc)123\1$");
if (r.IsMatch(x))
{
Console.WriteLine("group1 value:" + r.Match(x).Groups[].Value);//输出:null
}

2.贪婪模式和非贪婪模式

一般情况下,正则都是贪婪模式,尤其是在+或者*修饰的条件下,正则都会去尽可能的匹配更多的内容,但是如果添加了?号,这个时候立马就会变成非贪婪模式

 string x = "Live for nothing,die for something";
Regex r1 = new Regex(@".*thing");
if (r1.IsMatch(x))
{
Console.WriteLine("match:" + r1.Match(x).Value);//输出:Live for nothing,die for something
}
Regex r2 = new Regex(@".*?thing");
if (r2.IsMatch(x))
{
Console.WriteLine("match:" + r2.Match(x).Value);//输出:Live for nothing
}

3.回溯与非回溯

在默认情况下正则匹配贪婪模式下,当匹配的字符陷入死胡同的时候,会进行回溯直到下一个字符能够接着匹配

比如 (.*)abc  来匹配123abc123abc   首先.*会进行贪婪匹配直到匹配到字符结尾的位置,接着匹配a,发现没有字符可以匹配上,引擎就向后回溯,直到a匹配到最后abc中的a,然后紧接着匹配b,然后匹配c  所以结果是  123abc123abc

好,接着来说明下非回溯模式的执行过程,同样首先.*像一只饿狼般的匹配到字符的结尾位置,这个时候开始匹配a 发现已经无法匹配,此模式下,不进行回溯,于是匹配失败,在有的业务下我们需要这样的非回溯匹配 ,语法例:(?>.*)abc

4.正向预搜索反向预搜索

不好解释,举例说明

正向预搜索

string x = "1024 used 2048 free";
Regex r1 = new Regex(@"\d{4}(?= used)");
if (r1.Matches(x).Count==)
{
Console.WriteLine("r1 match:" + r1.Match(x).Value);//输出:1024
}
Regex r2 = new Regex(@"\d{4}(?! used)");
if (r2.Matches(x).Count==)
{
Console.WriteLine("r2 match:" + r2.Match(x).Value); //输出:2048
}

r1表示匹配后面紧跟着used的四个数字  于是乎匹配了1024      r2 匹配后面不是紧跟着used的四个数字  于是乎 匹配2048

反向预搜索

string x = "used:1024 free:2048";
Regex r1 = new Regex(@"(?<=used:)\d{4}");
if (r1.Matches(x).Count==)
{
Console.WriteLine("r1 match:" + r1.Match(x).Value);//输出:1024
}
Regex r2 = new Regex(@"(?<!used:)\d{4}");
if (r2.Matches(x).Count==)
{
Console.WriteLine("r2 match:" + r2.Match(x).Value);//输出:2048
}

r1匹配前面紧着着used:的四个数字 于是乎匹配1024    r2匹配前面不是紧跟着used:的四个数字  于是乎撇配2048

看着例子理解就很好理解了,另外正向和反向的组是不保存的

C#正则学习的更多相关文章

  1. js 正则学习小记之匹配字符串

    原文:js 正则学习小记之匹配字符串 今天看了第5章几个例子,有点收获,记录下来当作回顾也当作分享. 关于匹配字符串问题,有很多种类型,今天讨论 js 代码里的字符串匹配.(因为我想学完之后写个语法高 ...

  2. js 正则学习小记之左最长规则

    原文:js 正则学习小记之左最长规则 昨天我在判断正则引擎用到的方法是用 /nfa|nfa not/ 去匹配 "nfa not",得到的结果是 'nfa'.其实我们的本意是想得到整 ...

  3. js 正则学习小记之NFA引擎

    原文:js 正则学习小记之NFA引擎 之前一直认为自己正则还不错,在看 次碳酸钴,Barret Lee 等大神都把正则玩的出神入化后发现我只是个战五渣.  求抱大腿,求大神调教. 之前大致有个印象,正 ...

  4. js 正则学习小记之匹配字符串优化篇

    原文:js 正则学习小记之匹配字符串优化篇 昨天在<js 正则学习小记之匹配字符串>谈到 个字符,除了第一个 个,只有 个转义( 个字符),所以 次,只有 次成功.这 次匹配失败,需要回溯 ...

  5. js 正则学习小记之匹配字符串字面量优化篇

    昨天在<js 正则学习小记之匹配字符串字面量>谈到 个字符,除了第一个 个,只有 个转义( 个字符),所以 次,只有 次成功.这 次匹配失败,需要回溯后用 [^"] 才能匹配成功 ...

  6. php 正则学习取反符号~

    php 正则学习取反符号~ ~(<a .*?>.*?</a>|<.*?>)~i 先看正则图形,有点偏差,但可以初步看出结果. 关于 ~ 是取反符号,看下面说明.

  7. java 正则学习

    前言 在网上找了许多关于正则解析 URL,结果不是很满意,所以自己学习正则: java url 那么解析 url 的代码如下: import java.util.regex.Matcher; impo ...

  8. JavaScript(E5,6) 正则学习总结学习,可看可不看!

    1.概述 正则表达式(实例)是一种表达文本模式(即字符串结构)的方法. 创建方式有两种方式: 一种是使用字面量,以斜杠表示开始和结束. var regex = /xyz/ 另一种是使用RegExp构造 ...

  9. js正则学习及一些正则集合

    正则中文版详细说明请看中文版w3cschool-----http://www.w3school.com.cn/jsref/jsref_obj_regexp.asp微软正则表达式语言-快速参考:http ...

随机推荐

  1. codeforces Round #259(div2) E解决报告

    E. Little Pony and Summer Sun Celebration time limit per test 1 second memory limit per test 256 meg ...

  2. NSIS:使用PassDialog插件实现密码安装(卸载)功能

    原文 NSIS:使用PassDialog插件实现密码安装(卸载)功能 有时,出于特殊的需求,我们要给安装或卸载程序加一个密码,只有输入了正确的密码才可以继续.比如: 下面我们使用插件来实现安装密码: ...

  3. 实现键值对存储(三):Kyoto Cabinet 和LevelDB的架构比較分析

    译自  Emmanuel Goossaert (CodeCapsule.com) 在本文中,我将会逐组件地把Kyoto Cabinet 和 LevelDB的架构过一遍.目标和本系列第二部分讲的差点儿相 ...

  4. Gallatin(大陆版)Office365中Exchange Online混合部署功能已经能够使用了

    经过測试,Exchange混合部署已经能够使用了 前置条件: 本机至少须要一台Exchange Server 2013作为混合部署server 须要一个公网域名 domian.com,能够和内部域名不 ...

  5. Web 前端开发环境

    创建 Web 前端开发环境 Web 前端开发涉及多种工具,这里将常用工具的安装和配置进行说明,提供了详细的说明,为后继的开发创建一个坚实的基础. 本文介绍的工具有:NodeJS, NPM, Bower ...

  6. CentOS安装KVM步骤虚拟机,绝对实用!

    KVM(Kernel-based Virtual Machine)速记.这是rhel5.4最新的虚拟化技术启动,现在只支持红帽64位rhel5.4在执行KVM,硬件必须支持同一时间VT技术,网上找 ...

  7. Ajax 实现无刷新页面

    注意:如本文所用,在前面的文章库的数目可以在源代码中找到,我将指示在文本,其中链路,为了缩短制品的长度,阅读由此带来的不便.乞求被原谅. 评论文章 Ajax 实现无刷新页面.其原理.代码库.代码. 这 ...

  8. Spring3+SpingMVC+Hibernate4全注解环境配置

    Spring3+SpingMVC+Hibernate4全注解环境配置 我没有使用maven,直接使用Eclipse创建动态Web项目,jar包复制在了lib下.这样做导致我马上概述的项目既依赖Ecli ...

  9. java nio的一个严重BUG(转)

    这个BUG会在linux上导致cpu 100%,使得nio server/client不可用,具体的详情可以看这里http://bugs.sun.com/bugdatabase/view_bug.do ...

  10. C++ Primer Plus 文章17章 进,输出和文件

    文章17章 进.输出和文件 1.当到达输入句子.他将刷新输出缓冲区满输出电流 2.streambuf分类 它提供了用于各种操作的一个缓冲 ios_base类表示流的一般特征 ios基础的类ios_ba ...