站点图标 久久日记本

C#中的正则表达式

本文目录

目录

*1.基础

*2.实例

1.基础

在学习本文之前,可以先阅读和练习下下面链接文档,它是我读过的正则中最好的一篇文章:

.NET进阶系列之一:C#正则表达式整理备忘>>传送门

依靠该篇博文,基本学会了正则表达式!感谢Morven.Huang博主!

WinForm代码片段需要引用的命名空间:

using System.Text.RegularExpressions;

统计匹配弹出框:

MessageBox.Show("r match:"+r.Match(i).Value);
MessageBox.Show(r.IsMatch(i).ToString() + "," + r.Matches(i).Count);

相关练习(参考自上述文章自己的练习):

1.@ /的用法:

/*@*/
//在相关有"/","""等表达符号特殊字符中要用到;
//  "/"用于转义

2.基本语法字符:

/*基本字符语法*/
//string i = "123?!_";
//Regex r = new Regex(@"\d");//true 数字
//Regex r = new Regex(@"\D");//true 非数字 \d的补集
//Regex r = new Regex(@"\w");//true 单词字符,a-z,A-Z,0-9,_
//Regex r = new Regex(@"\W");//true \w的补集
//Regex r = new Regex(@"\s");//false 空白字符(包括换行符 \n,回车符 \r,制表符 \t,垂直制表符 \v,换页符 \f)
//Regex r = new Regex(@"\S");//true \s的补集
//Regex r = new Regex(".");//true 除换行符\n外的任意字符
//Regex r = new Regex("[...]");//false 匹配[]内所列出的所有字符
//Regex r = new Regex("[5-6]");//flase
//Regex r = new Regex("[^...]");//true 匹配非[]内所列出的字符

3.定位字符:

/*定位字符*/
//string i = "Live for nothing,Die for nothing!";
//Regex r = new Regex("^for nothing");//flase ^ 表示其后的字符串必须位于字符串开始处
//Regex r = new Regex("^Live for");//true 

//Regex r = new Regex("nothing$");//false $ 表示其前面的字符必须位于字符串结束处 
//Regex r = new Regex("nothing!$");//true

/*string i = @"Live for nothing,
Die for nothing!";//多行*/
/*Regex r = new Regex(@"^Live for nothing,
Die for nothing!");//true*/
//Regex r = new Regex("^Live for nothing,\r\nDie for nothing!$");//true
//Regex r = new Regex("^Live for nothing,\r\n$",RegexOptions.Multiline);//false ???
//对于一个多行字符串,在设置了Multiline选项之后,^和$将出现多次匹配

//string i = "Live for nothing,Die for no thing!";
//Regex r = new Regex(@"thing\b");//true,2; b:匹配一个单词的边界;B:匹配一个非单词的边界
//Regex r = new Regex(@"\bthing\b");//true,1;
//Regex r = new Regex(@"\bfor nothing");//true,1;
//Regex r = new Regex(@"\bfor nothing\b");//true,1;

4.重复描述字符:

/*重复描述字符*/
//string i = "1024";//true,1
//string i = "-1023";//true,1
//string i = "-12.12";//false
//Regex r = new Regex(@"^\+?\-?[0-9].?\d{3}$");//匹配+或者- 1(.)000

//string i = "dong3580@163.com";//true ,1
//string i = "dong3580@";
//Regex r = new Regex(@"^\w+@\w+.[a-z]+");//验证email地址

5.择一匹配:

/*择一匹配 ( | ) or语句*/
//string i = "0";       //F T 1
//string i = "0.23";  //F T 1
//string i = "100";   //T F 1
//string i = "100.01";//F F 0
//string i = "9.9";   //F T 1
//string i = "99.9";  //F T 1
//string i = "99.";   //F F 0
//string i = "00.1";  //F F 0
//Regex r = new Regex(@"^\+?((100(.0+)*)|([1-9]?[0-9])(\.\d+)*)$");//^\+?((100(\.0)?)|([1-9]?[0-9])(\.\d+)?)$
//匹配0到100的数。最外层的括号内包含两部分“(100(.0+)*)”,“([1-9]?[0-9])(\.\d+)*”,这两部分是“OR”的关系,即正则表达式引擎会先尝试匹配100,如果失败,则尝试匹配后一个表达式(表示[0,100)范围中的数字)。

6.组与非捕获组

/*组与非捕获组*/
//string i = "Live for nothing,Die for something!";
//Regex r = new Regex(@"^Live ([a-z]{3}) no([a-z]{5}),Die \1 some\2!$");//True,1
//正则表达式引擎会记忆“()”中匹配到的内容,作为一个“组”,并且可以通过索引的方式进行引用。表达式中的“\1”,用于反向引用表达式中出现的第一个组,即粗体标识的第一个括号内容,“\2”则依此类推。

//Regex r = new Regex(@"^Live for no([a-z]{5}),Die for some\1!$");//True,1
//MessageBox.Show("Group1 value:"+r.Match(i).Groups[1].Value);//输出thing
//获取组中的内容。注意,此处是Groups[1],因为Groups[0]是整个匹配的字符串,即整个变量x的内容。

//Regex r = new Regex(@"^Live for no(?<g1>[a-z]{5}),Die for some\1!$");
//MessageBox.Show("Group1 value:"+r.Match(i).Groups[1]+",g1 value:"+r.Match(i).Groups["g1"].Value);//thing,thing;true 1
//可根据组名进行索引,使用一下格式为标识一个组的名称(?<groupname>...)

//string i = "Live for nothing nothing";
/*
Regex r = new Regex(@"([a-z]+) \1");
MessageBox.Show("Group1 value:"+r.Match(i).Groups[1].Value);//nothing
i = r.Replace(i,"$1");
MessageBox.Show("var i:"+i);//Live for nothing
//删除原字符串中重复出现的"nothing".在表达式之外,使用"$1"来引用第一个组,下面则是通过组名来引用.
*/

/*
Regex r = new Regex(@"(?<g1>[a-z]+) \1");
MessageBox.Show("Group1 value:"+r.Match(i).Groups["g1"].Value);//thing
i = r.Replace(i,"${g1}");//注意组名要用大括号括起来
MessageBox.Show("var i:"+i);//Live for nothing
*/

/*
Regex r = new Regex(@"^Live for nothing no(?:[a-z]{5})$");
MessageBox.Show("group1 value:"+r.Match(i).Groups[1].Value);//输出为空,
//在组前加上"?:"表示这是个"非捕获组",即引擎将不保存改组的内容
*/

7.贪婪与非贪婪:

/*贪婪与非贪婪*/
//string i = "Live for nothing,Die for nothing";
//Regex r = new Regex(@".*thing");//输出的是 Live for nothing,Die for nothing
//Regex r = new Regex(@".*?thing");//Live for nothing
//正则表达式的引擎是贪婪,只要模式允许,它将匹配尽可能多的字符。通过在“重复描述字符”(*,+)后面添加“?”,可以将匹配模式改成非贪婪。

8.回溯与非回溯:

/*回溯与非回溯*/
//Regex r = new Regex(@".*thing,");//Live for nothing //在r1中,“.*”由于其贪婪特性,将一直匹配到字符串的最后,随后匹配“thing”,但在匹配“,”时失败,此时引擎将回溯,并在“thing,”处匹配成功。
//Regex r = new Regex(@"(?>.*)thing,");//在r2中,由于强制非回溯,所以整个表达式匹配失败
//MessageBox.Show("match value:"+r.Match(i).Value);
//使用“(?>…)”方式进行非回溯声明。由于正则表达式引擎的贪婪特性,导致它在某些情况下,将进行回溯以获得匹配,

9.正向预搜索,反向预搜索:

/*正向预搜索,反向预搜索*/
string i = "1024 used 2048 free";
//Regex r = new Regex(@"\d{4}(?= used)");//1024
//Regex r = new Regex(@"\d{4}(?! used)");//2048
//r1中的正声明表示必须保证在四位数字的后面必须紧跟着“ used”,r2中的负声明表示四位数字之后不能跟有“ used”。
//正向预搜索声明格式:正声明 “(?=…)”,负声明 “(?!...)” ,声明本身不作为最终匹配结果的一部分,
/*反向预搜索   类似*/
2.案例

学习了C#中的正则表达式,自己尝试了写了一些提取相关信息和匹配验证,马马虎虎.

引用命名空间:

using System.Text.RegularExpressions;

案例1:验证email地址:
注册时常会用到email绑定,验证email的合法性在此.

WinForm界面:

TextBox: txtemail;
Button: btnCheck;

btnCheck点击事件:

private void btnCheck_Click(object sender, EventArgs e)
{
    string i = txtemail.Text.Trim();
    Regex r = new Regex(@"^\w+@\w+.[a-z]+");//xx@xx.xx
    if (r.IsMatch(i))
    {
        MessageBox.Show("格式正确!");
    }
    else
    {
        MessageBox.Show("格式错误!");
    }
}

案例2:提取网页源码的ed2k链接:

(1)对VeryCD的备份中会用到提取链接,可以先遍历网页的id号;

(2)根据url获取网页源码并利用正则表达式 提取ed2k链接 和对应的标题;

(3)存入listbox并写入为txt文本.

关于这些 备份VeryCD 和RSS阅读器 的相关实现会在后面研究.

WinForm界面:

TextBox: txtemail;

Button: btnCheck;

btnCheck点击事件:

private void btngeted2k_Click(object sender, EventArgs e)
{
    string i = txtemail.Text.Trim();
    Regex r = new Regex(@"[ed2k://|]{8}[a-z]+[|][^|]?\w+[.]+[^|]+[|]");//匹配ed2k链接
    //string j = r.Match(i).ToString();
    MatchCollection j = r.Matches(i);
    //j = j.Substring(0, j.Length - 1);
    //去掉提取字符串的换行,因为假如保存的源码中txt文本自动换行的话
    if (r.IsMatch(i))
    {
        string str="",temp="";
        for (int c = 0; c < j.Count; c++)
        {
            temp=j[c].ToString();
            str += temp.Substring(0, temp.Length - 1)+"\n\n";
        }

        MessageBox.Show(str);
        //MessageBox.Show(r.Match(i).ToString());

    }
    else
    {
        MessageBox.Show("尚未提取出ed2k链接!");
    }
}

案例3:提取cnblogs首页的文章链接地址:

适合做个RSS阅读,只保留文字.

主界面同上

private void btnGetCnblogs_Click(object sender, EventArgs e)
{
    string i = txtemail.Text.Trim();
    Regex r = new Regex(@"[a-z]{4}[:]+//[w]{3}[^ ]+/[0-9]+.[html]{4}");
    MatchCollection j = r.Matches(i);
    if (r.IsMatch(i))
    {
        string str="";
        for (int c = 0; c < j.Count; c++)
        {
            if (c + 1 < j.Count)
            {
                if (j[c].ToString() != j[c + 1].ToString())
                    //去掉相邻两个重复的链接,当相邻两个链接不相等时才将前一个存入str;
                    //因为博客园里面同一篇文章会提取出相同的三个链接
                {
                    //list.Add(j[c].ToString());
                    str += j[c].ToString() + "\n\n";
                }
            }
        }
        str=str+j[j.Count - 1].ToString();

        MessageBox.Show(str);
        //MessageBox.Show(r.Match(i).ToString());

    }
    else
    {
        MessageBox.Show("尚未提取cnblogs文章链接!");
    }
}
退出移动版