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

以前在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. leetcode文章137称号-Single Number II

    #include<stdio.h> #include<stdlib.h> int singleNumber(int* nums, int numsSize) { int cou ...

  2. SQL Server 日期相关

    原文:SQL Server 日期相关 原帖出处:http://blog.csdn.net/dba_huangzj/article/details/7657979 对于开发人员来说,日期处理或许简单,或 ...

  3. JAVA该队列中的数组,圆阵队列,链队列

    /** * 文件名:QueueText.java * 时间:2014年10月22下午9:05:13 * 笔者:维亚康姆维修 */ package chapter3; /** * 类名:ArrayQue ...

  4. java设计模式:观察者模式

    package Observer; public class Test { /** * client测试类别 * 观察者模式一般由四部分组成: * 1摘要观察员(教科书被称为一般"Subje ...

  5. BZOJ 1212 HNOI2004 L语言 AC自己主动机(Trie树)+动态规划

    标题效果:给定词的列表,并m串 每个字符串q个最长前缀,这个前缀可满足拆分成一些字符串 这些字符串中存在的词汇太 再也不怕错误的数据范围--有一个很明显Trie树能解决的问题竟然被我写的AC自己主动机 ...

  6. 求N!末尾的0的个数(找规律+递归)

    0\'s Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描写叙述 计算整数n!(n的阶乘)末尾有多少个0. 输入 第一行输入一个数T代 ...

  7. 2014年辛星全然解读html第八节

    经过前面七节的学习,我感觉大家的HTML的功底也差点儿相同了,并且我特别的删去了某些东西,比方框架,假设回到几年前,那么框架是很流行的,可是如今都到了2014年了,这些东西早就该被遗忘了,因此,我果断 ...

  8. 飞天熊猫游戏源代码android文本

    这款游戏是前一段时间完毕的一个项目,飞行熊猫游戏源代码android版.飞行熊猫基于cocos2d游戏引擎开发.包含了谷歌admob广告支持,没有不论什么版权问题.大家能够自由改动和上传应用商店. 1 ...

  9. android使用ffmpeg

    cygwin上文编译文章. 在ffmpeg/arm添加的文件夹Android.mk 的主要目的是为了宣布动态库libs下一个 LOCAL_PATH:= $(call my-dir) include $ ...

  10. google面试题,男孩男女比例?

    Google面试题: 在一个重男轻女的国家里,每一个家庭都想生男孩.假设他们生的孩子是女孩.就再生一个,直到生下的是男孩为止,这种国家.男女比例会是多少? 答案:1:1 分析:  出生男女概率是50% ...