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

以前在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. ORM武器:NHibernate(三)五个步骤+简单对象CRUD+HQL

    前面的两篇文章中.我们对NHibernate已经做了大致了解 <ORM利器:NHibernate(一)简单介绍>Nhibernate的作用:攻克了对象和数据库的转化问题 <ORM利器 ...

  2. JSTL实现int数据的类型的长度

    JSTL否int类型转换string该功能.为了解决增益int数据的类型的长度,闹失踪. 得到String的数据的长度是jstl的fn能够${fn:length(string)},但int做数据? 经 ...

  3. 代理下载android4.4源代码

    前提条件:需要有user, password, 代理人serverip和port(这一切都使自己的软件来完成下一个.例如freegate,它拥有一套可以自己作为一个代理server.创user/pas ...

  4. 示例:Netty 处理 TCP数据分包协议

    一个.Netty解决TCP协议的数据分包的想法 我们知道通过TCP协议发送接收数据时,假设数据过大.接收到的数据会是分包的.比方:                                   ...

  5. hibernate 双向n-n

    领域模型: 关系数据模型 双向 n-n 关联须要两端都使用集合属性 双向n-n关联必须使用连接表 集合属性应添加 key 子元素用以映射外键列, 集合元素里还应添加many-to-many子元素关联实 ...

  6. 这个夏天不AC(杭州电2037)

    这个夏天不AC Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Su ...

  7. CentOS7 安装spark集群

    Spark版本 1.6.0 Scala版本 2.11.7 Zookeeper版本 3.4.7 配置虚拟机 3台虚拟机,sm,sd1,sd2 1. 关闭防火墙 systemctl stop firewa ...

  8. PHP memcache实现消息队列实例

    现在,memcache于server缓存广泛应用.下面我来介绍一下memcache消息队列中等待的样本实现,有需要了解的朋友可以参考. memche消息队列原则key上做文章.后消息或者日志. 然后通 ...

  9. SQL Profile (总结4)--使用演示示例

    前提:sql profile工具的相关视图 dba_sql_profile 10g: sys.sqlprof$attr  &  sqlprof$ 11g: sys.sqlobj$data  & ...

  10. .NET中lock的使用方法及注意事项

    lock就是把一段代码定义为临界区,所谓临界区就是同一时刻只能有一个线程来操作临界区的代码,当一个线程位于代码的临界区时,另一个线程不能进入临界区,如果试图进入临界区,则只能一直等待(即被阻止),直到 ...