• 正则表达式入门(2)


    示例2

    e-mail的匹配

    就从博客园的联系方式页面来找就好了,地址是 http://www.cnblogs.com/ContactUs.aspx

    准备工作:

    获取页面内容,方法如下:

    static string DownloadString(Uri url, Encoding encoding)
    {
        WebClient client;
        using (client = new WebClient())
        {
    return encoding.GetString(client.DownloadData(url));
        }
    }

    只适用于简单的情况,已经足够了,下面是示例

    static void example2()
    {
        Uri url;
        Encoding encoding;
        string content;
        Regex regex;
        MatchCollection matches;
    
        string expression;
    
        url = new Uri("http://www.cnblogs.com/ContactUs.aspx");
        encoding = Encoding.UTF8;//博客园是utf-8的,直接指定了
    
        content = DownloadString(url, encoding);
    
        expression = "[-_0-9A-Z]{1,20}(@|&\#64;)[-0-9A-Z]+(\.com|\.net)";
    
        regex = new Regex(expression, RegexOptions.IgnoreCase | RegexOptions.Singleline);
    
        matches = regex.Matches(content);
    
        foreach (Match match in matches)
        {
            Console.WriteLine(string.Concat("'", match.Value.Replace("@", "@"), "'"));
        }
    }

    e-mail 的格式为 {用户名}@{域名}

    为了看起来比较简单,我们假设用户名只能由"-","_",0-9的数字和A-Z的字母 组成

    所以用户名部分就是[-_0-9A-Z],但是有一点需要注意,第一个"-"和后面的"-"的含义是不一样的,第一个的意思是"-"这个字符本身,后面的代表的是范围,范围是通过"a-b"这样的方式来确定的,如果需要匹配"-"这个字符本身,尽量不要放在歧义的位置。

    然后是第二部分 "(@|&\#64;)" 是包含在括号之间的,原因在于这里由2部分组成,其中用|分开,表示多选一,"@" 或者 "@"(@的ascii就是64,可以用"@",  "#"字符在正则中需要转义,需要转义的字符可以在msdn中找到,地址是 http://msdn.microsoft.com/zh-cn/library/system.text.regularexpressions.regex.escape(v=vs.110).aspx,需要转义的字符只要在前面加上"\"即可)如果外面没有括号来限制,那这个多选分支的范围就扩大了,把"|"两边作为一个多选分支,那就变成了  "{用户名}@" 或者 "@{域名}",不是我们想要的情况。

    [-0-9A-Z]+(\.com|\.net)

    最后是域名部分,目前只接受".net"或者".com"这2个顶级域名 类似 "cnblogs.com" 这样的形式

    前面部分由至少一个的 数字,字母或者"-"组成,后面只允许".com"或者".net"还是用|来做到

    最后 RegexOptions.IgnoreCase 表示忽略大小写,不然,这个表达式可能要写成

    "[-_0-9A-Za-z]{1,20}(@|&\#64;)[-0-9A-Za-z]+(\.[cC][oO][mM]|\.[nN][eE][tT])"
    不够直观
     

    好了,看一下结果

    'contact@cnblogs.com'
    'contact@cnblogs.com'

    一共有2个匹配

    不过,如果要把用户名和域名都取出来好像有点麻烦

    稍微改进一下,代码如下:

    static void example2()
    {
        Uri url;
        Encoding encoding;
    string content;
        Regex regex;
        MatchCollection matches;
    
    string expression;
    
        url = new Uri("http://www.cnblogs.com/ContactUs.aspx");
        encoding = Encoding.UTF8;
    
        content = DownloadString(url, encoding);
    
        expression = "([-_0-9A-Z]{1,20})(@|&\#64;)([-0-9A-Z]+(\.com|\.net))";
    
        regex = new Regex(expression, RegexOptions.IgnoreCase | RegexOptions.Singleline);
    
        matches = regex.Matches(content);
    
    foreach (Match match in matches)
        {
            Console.WriteLine(string.Format(
    "e-mail: '{0}', userName: '{1}', domain: '{2}'",
                match.Groups[0].Value.Replace("@", "@"),
                match.Groups[1].Value,
                match.Groups[3].Value
            ));
        }
    }

    先看看改动

    "[-_0-9A-Z]{1,20}" 变成了 "([-_0-9A-Z]{1,20})"

    "[-0-9A-Z]+(\.com|\.net)" 变成了 "([-0-9A-Z]+(\.com|\.net))"

    只是在外面加了对括号

    默认情况下,会为每对括号创建一个捕获分组(capture group)

    看一下完整的表达式 "([-_0-9A-Z]{1,20})(@|&\#64;)([-0-9A-Z]+(\.com|\.net))"

    第一个分组是:"([-_0-9A-Z]{1,20})"

    第二个分组是:"(@|&\#64;)"

    第三个分组是:"([-0-9A-Z]+(\.com|\.net))"

    第四个分组是:"(\.com|\.net)"

    其中第四个是嵌套在第三个之中

    这样,就可以通过Match.Groups[下标]来获取对应的分组了,其中Groups[0]就是完整的匹配

    这样还是不够直观,再做一次更改

    改动后代码如下:

    static void example2()
    {
        Uri url;
        Encoding encoding;
        string content;
        Regex regex;
        MatchCollection matches;
    
        string expression;
    
        url = new Uri("http://www.cnblogs.com/ContactUs.aspx");
        encoding = Encoding.UTF8;
    
        content = DownloadString(url, encoding);
    
        expression = "(?<userName>[-_0-9A-Z]{1,20})(@|&\#64;)(?<domain>[-0-9A-Z]+(\.com|\.net))";
    
        regex = new Regex(expression, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.ExplicitCapture);
    
        matches = regex.Matches(content);
    
        foreach (Match match in matches)
        {
            Console.WriteLine(string.Format(
                "e-mail: '{0}', userName: '{1}', domain: '{2}'",
                match.Groups[0].Value.Replace("&#64;", "@"),
                match.Groups["userName"].Value,
                match.Groups["domain"].Value
            ));
        }
    }

    "([-_0-9A-Z]{1,20})"变成了"(?<userName>[-_0-9A-Z]{1,20})"

    "([-0-9A-Z]+(\.com|\.net))"变成了"(?<domain>[-0-9A-Z]+(\.com|\.net))"

    都是在括号开始的地方加上了?<名称>

    这是命名分组捕获可以用以下方式调用

    match.Groups["userName"]

    match.Groups["domain"]

  • 相关阅读:
    C# 实现 Aop [Emit动态生成代理类方式]
    分享一些最近在看的电子书
    Can't connect to your phone. Disconnect it, restart it, then try connecting again
    07,Windows Phone后台代理
    .NET 性能测试工具 性能计数器
    windows 8 metro 开发学习资源链接
    08,Windows Phone 本地存储
    06,Windows Phone 8程序的生命周期
    .NET 性能测试工具 事件跟踪器(ETW)
    LitJSONjson 和net 的完美组合用法
  • 原文地址:https://www.cnblogs.com/afox/p/3525549.html
Copyright © 2020-2023  润新知