加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

正则表达式

发布时间:2020-12-13 22:05:35 所属栏目:百科 来源:网络整理
导读:正则表达式是一个用于匹配、提

正则表达式是一个用于匹配、提取、替换的包含元字符的字符串。
正则表达式中用进行转义。

基本元字符

.  任意的一个非换行字符
[] 集合匹配,表示匹配一个出现在[]中的一个字符
|  或:a|ab,敏感词:病毒|大麻
() 提高优先级实现分组,abc->a(bc)

限定元字符

+    紧跟在+前面的字符出现>=1次
*    紧跟在*前面的字符出现>=0次
?    紧跟在?前面的字符出现0或1次
{n}  [0123456789]{11}表示数字出现11次
{n,} [5-9]{8,}表示5-9之间的数字出现>=8次,{1,}等价于+
{n,m}[0-9]{3,6}表示0-9之间的数字出现3-5次
w   匹配包括下划线在内的任意单词字符(包括汉字),约等价于[0-9a-zA-Z_]
W   匹配任何非单词字符,约等价于[^0-9a-zA-Z_]
s   匹配任何空白字符包括换页符、回车符、换行符、制表符、垂直制表符,等价于[frntv]
S   匹配任何非空白字符,等价于[^frntv]
d   匹配一个数字字符,等价于[0-9]
D   匹配一个非数字字符,等价于[^0-9]

匹配邮箱示例代码:

static void Main(string[] args)
{
    WebClient wc = new WebClient();
    wc.Encoding = Encoding.UTF8;
    string html = wc.DownloadString("http://tieba.baidu.com/p/2314539885");
    //【正则表达式1】
    //string regex = @"w+@w+(.w+)+";
    //【正则表达式2(改进版)】
    string regex = @"[0-9a-zA-Z_-.]+@[0-9a-zA-Z_]+(.[0-9a-zA-Z_]+)+";
    MatchCollection mc = Regex.Matches(html,regex);
    int i = 0;
    foreach (Match match in mc)
    {
        Console.WriteLine(i++ + "," + match.Value);
    }
    Console.ReadKey();
}

示例正则表达式解析:

示例邮箱地址:99999@china.com
正则表达式1:@”w+@w+(.w+)+”
正则表达式1格式解析:
①@符号表示对字符串中的进行转义
②w+ 匹配”99999”部分
③@ 匹配”@”
④w+ 匹配”china”部分
⑤(.w+) 匹配”.com”部分
⑥(.w+)+ 匹配至少一个”.com”部分,当邮箱是99999@china.vip.com格式时也能匹配到
⑦表达式1有个问题,即可以匹配到”12345@qq.com楼主好人”,因为w可以匹配汉字,因此有了改进版的表达式2

正则表达式2:@”[0-9a-zA-Z_-.]+@[0-9a-zA-Z_]+(.[0-9a-zA-Z_]+)+”
正则表达式2格式解析:
①@符号表示对字符串中的进行转义
②[0-9a-zA-Z_-.]+ 匹配”99999”部分
③@ 匹配”@”
④[0-9a-zA-Z_]+ 匹配”china”部分
⑤(.[0-9a-zA-Z_]+) 匹配”.com”部分
⑥(.[0-9a-zA-Z_]+)+ 匹配至少一个”.com”部分,当邮箱是99999@china.vip.com格式时也能匹配到
⑦表达式2不能匹配到”12345@qq.com楼主好人”,能匹配到”12345@qq.com”,比表达式1更精确

^和$

^once表示只匹配那些以”once”开头的字符串,^once[0-9][a-z]end表示只匹配以”once[0-9][a-z]end”开头的字符串。
用两个同样的匹配规则,一个加^、一个不加^进行匹配结果对比,更容易理解,示例代码如下:

public void TestStart()
{
    int i = 0;
    bool flag;
    string input = "once1aend";
    string regex = @"once[0-9][a-z]end";
    string regexStart = @"^once[0-9][a-z]end";
    Console.WriteLine("【"+input + "匹配" + regexStart + "的结果:】");
    flag = Regex.IsMatch(input,regex);
    Console.WriteLine("是否匹配=" + flag);
    MatchCollection mc = Regex.Matches(input,regexStart);
    foreach (Match match in mc)
    {
        Console.WriteLine(i++ + "," + match.Value);
    }
    Console.WriteLine("【" + input + "匹配" + regex + "的结果:】");
    flag = Regex.IsMatch(input,regex);
    Console.WriteLine("是否匹配=" + flag);
    Console.WriteLine("匹配项:");
    mc = Regex.Matches(input,regex);
    i = 0;
    foreach (Match match in mc)
    {
        Console.WriteLine(i++ + "," + match.Value);
    }
    Console.ReadKey();
}

运行结果如图:

将变量input的值修改为”once1aend666”,运行结果如图:

将变量input的值修改为”once1aend666once2bend”,运行结果如图:

将变量input的值修改为”666once1aend”,运行结果如图:

^对比结论:

  • “^once[0-9][a-z]end”只能匹配以此开头的字符串,若字符串中有多条内容符合”once[0-9][a-z]end”格式,也只能匹配到一条,匹配结果是符合匹配格式的字符串开头,建议使Regex.Match()。
  • “once[0-9][a-z]end”可以匹配到字符串中满足此格式的任意位置的内容,而且可以匹配到多条,建议使用Regex.Matchs()。

once$表示只匹配那些以”once”结尾的字符串,once[0-9][a-z]end$表示只匹配以”once[0-9][a-z]end”结尾的字符串。
用两个同样的匹配规则,一个加$、一个不加$进行匹配结果对比,更容易理解,示例代码如下:

public void TestEnd()
{
    int i = 0;
    bool flag;
    string input = "once1aend";
    string regex = @"once[0-9][a-z]end";
    string regexEnd = @"once[0-9][a-z]end$";
    Console.WriteLine("【" + input + "匹配" + regexEnd + "的结果:】");
    flag = Regex.IsMatch(input,regexEnd);
    Console.WriteLine("是否匹配=" + flag);
    Console.WriteLine("匹配项:");
    //【改进】匹配^......$只有一个结果,所以用Match()而不是Matchs()
    Match match = Regex.Match(input,regexEnd);
    Console.WriteLine(i++ + "," + match.Value);
    Console.WriteLine("---------------------------------");
    Console.WriteLine("【" + input + "匹配" + regex + "的结果:】");
    flag = Regex.IsMatch(input,regex);
    Console.WriteLine("是否匹配=" + flag);
    Console.WriteLine("匹配项:");
    MatchCollection mc = Regex.Matches(input,regex);
    i = 0;
    foreach (Match obj in mc)
    {
        Console.WriteLine(i++ + "," + obj.Value);
    }
}

运行结果如图:

将变量input的值修改为”once1aend666”,运行结果如图:

将变量input的值修改为”once1aend666once2bend”,运行结果如图:

将变量input的值修改为”666once1aend”,运行结果如图:

$对比结论:

  • “once[0-9][a-z]end$”只能匹配以此结尾的字符串,若字符串中有多条内容符合”once[0-9][a-z]end”格式,也只能匹配到一条,匹配结果是符合匹配格式的字符串结尾,建议使Regex.Match()。
  • “once[0-9][a-z]end”可以匹配到字符串中满足此格式的任意位置的内容,而且可以匹配到多条,建议使用Regex.Matchs()。

^once$表示只匹配”once”字符串,^once[0-9][a-z]end$表示只匹配”once[0-9][a-z]end”字符串。
示例代码:

public void TestStratEnd()
{
    int i = 0;
    bool flag;
    string input = "once1aend";
    string regex = @"once[0-9][a-z]end";
    string regexStartEnd = @"^once[0-9][a-z]end$";
    Console.WriteLine("【" + input + "匹配" + regexStartEnd + "的结果:】");
    flag = Regex.IsMatch(input,regexStartEnd);
    Console.WriteLine("是否匹配=" + flag);
    Console.WriteLine("匹配项:");
    Match match = Regex.Match(input,regexStartEnd);
    Console.WriteLine(i++ + "," + match.Value);
    Console.WriteLine("--------------------------------");
    Console.WriteLine("【" + input + "匹配" + regex + "的结果:】");
    flag = Regex.IsMatch(input,regex);
    Console.WriteLine("是否匹配=" + flag);
    Console.WriteLine("匹配项:");
    MatchCollection mc = Regex.Matches(input,regex);
    i = 0;
    foreach (Match obj in mc)
    {
        Console.WriteLine(i++ + "," + obj.Value);
    }
}

运行结果如图:

将变量input的值修改为”once1aend666”,运行结果如图:

将变量input的值修改为”once1aend666once2bend”,运行结果如图:

将变量input的值修改为”666once1aend”,运行结果如图:

^$对比结论:

  • “^once[0-9][a-z]end$”只能匹配符合”once[0-9][a-z]end”格式且不包含任何其他字符的字符串,建议使Regex.Match()。
  • “once[0-9][a-z]end”可以匹配到字符串中满足此格式的任意位置的内容,而且可以匹配到多条,建议使用Regex.Matchs()。
  • 当我们需要判断字符串是否是整数、小数类型时,可以使用^$来帮助我们。

匹配HTML标签

使用"<html><body></body></html>"来匹配"<.+>",只能匹配到一个满足项,"html><body></body></html"都被匹配到.+中了,所以只有一个满足项。截图如下:
如果我们相匹配完整的HTML标签时,内容中不应该有">",改进后,使用<html><body></body></html>来匹配"<[^>]+>",能匹配到四个满足项,截图如下(实际中遇到类似情况知道怎么去改进就行了):

使用分组

如果我们在正则提取过程中希望得到匹配项,同时需要使用匹配项中的某一部分的时候,使用分组可以方便的实现这个功能,只需要用圆括号把需要的部分括起来即可,例如:(.+)。
分组编号及使用:

  • Match对象有一个Groups的属性,Groups存储正则表达式匹配到的组
  • 根据需要加括号对数据进行分组,括号必须成对
  • 从左往右数”(“,索引从1开始
  • 第0组是字符串本身,m.Groups[0].Value==m.Value
  • 匹配完成后使用Groups[index]即可访问所需的内容

示例代码如下:

public void TestGroup()
{
    string regex = @"^(([0-9]+)([a-z]+))([0-9]+)$";
    string input = "123abc456";
    Match match = Regex.Match(input,regex);
    for (int i = 0; i < match.Groups.Count; i++)
    {
        Console.WriteLine("match.Groups[" + i + "]=" +match.Groups[i].Value); } Console.ReadKey(); }

运行结果如图:

贪婪模式

正则表达式默认匹配尽可能多,示例代码如下:

public void TestGreed()
{
    string input = "1234567890";
    string regex = @"^(d+)(d+)(d+)$";
    Match match = Regex.Match(input,regex);
    for (int i = 0; i < match.Groups.Count; i++)
    {
        Console.WriteLine("match.Groups[" + i + "]=" +match.Groups[i].Value); } Console.ReadKey(); }

运行结果如图:

默认匹配尽可能多,所以Groups[1]匹配了最多,只给Groups[2]、Groups[3]留了一个数字,留一个是因为Groups[2]、Groups[3]对应(d+),+表示数量>=1,最小值是1,所以留了一个。
如果正则表达式变为string regex = @”^(d+)(d*)(d*)$”;,那Groups[2]、Groups[3]的值均为空,因为*表示数量>=0,最小值是0,所以一个不留。
运行结果如图:

?可以取消贪婪,取消第一个分组的贪婪模式后,第二个分组的权限会变得最大(即第二分组贪婪),string regex = @”^(d+?)(d+)(d+)$”;,运行结果如图:

一般在写正则表达式的时候,不需要去考虑贪婪的问题,直接写就行。如果出现了匹配结果比预期多的情况,一般是贪婪造成的,再去考虑取消贪婪的问题。

匹配一个整数

整数分为:0、正整数、负整数,不允许出现0123这种形式
包含匹配:”0|-?[1-9][0-9]*”,123abc456可以匹配到两个满足条件的结果——123和456,实际上123abc456不是正确的数字格式。
绝对匹配:”^0|-?[1-9][0-9]*$”,123abc456可以匹配到满足条件的结果456,因为”^0|-?[1-9][0-9]*$”等价于”(^0)|(-?[1-9][0-9]*$)”,如果写成”^(0|-?[1-9][0-9]*$)”那123abc456就匹配不到了

正则替换

public void TestReplace()
{
    string input = "ab------c---d---ef----g";
    string result = Regex.Replace(input,@"-+","-");
    Console.WriteLine("input=" + input);
    Console.WriteLine("result=" + result);
}

运行结果如图:

引用匹配到的数据:
要引用前面匹配到的结果,可以使用$引用前面匹配到的部分,$0表示把前面匹配到的第0组拿过来,第0组是字符串本身,m.Groups[0].Value==m.Value,如果继续加”()”的话,可以用$1、$2……来引用

protected void Page_Load(object sender,EventArgs e)
{
    if (!IsPostBack)
    {
        Label1.Text = "http://www.baidu.com123 4 5 6http://www.csdn.net/";
    }
}
protected void btnReplace_Click(object sender,EventArgs e)
{
    string input = "http://www.baidu.com123 4 5 6http://www.csdn.net/";
    //不加()
    string result = Regex.Replace(input,@"http://[w.]+.[a-z]+","<a href="$0">$0</a>");
    //加上(),result==resultAdd
    string resultAdd = Regex.Replace(input,@"(http://[w.]+.[a-z]+)","<a href="$1">$1</a>");
    Label1.Text = result;
}

点击替换按钮之前:

点击替换按钮之后:

注意

一般,正则表达式很难一次就写得完美,我们可以先写出来测试一下,然后根据匹配到的结果,逐步精细化正则表达式以达到自己的目的。
测试正则表达式可以使用RegexTester工具。
注意

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读