正则表达式内容汇总

1 元字符

  正则表达式(Regular Expression,Regex),是计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。这里汇总了一些正则表达式的常用元字符。

元字符 描述
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。串行“\\”匹配“\”而“\(”则匹配“(”。
^ 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
$ 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
* 匹配前面的子表达式零次或多次。例如,zo*能匹配“z”以及“zoo”。*等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
? 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}。
{n} n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,} n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m} m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
?(非贪婪) 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。
. 匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。
(pattern) 获取分组,匹配pattern并获取这一匹配。正则表达式中的括号会默认进行分组,在C#中,match.Groups[0]是完整的匹配结果,match.Groups[1]是第一个括号内的匹配结果,match.Groups[2]是第二个括号内的匹配结果,依次类推。要匹配圆括号字符,请使用“\(”或“\)”。
(?:pattern) 非获取分组,匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“cit(?:y|ies)”就是一个比“city|cities”更简略的表达式。
(?=pattern) 正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。
(?!pattern) 正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
(?<=pattern) 反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
(?<!pattern) 反向否定预查,与正向否定预查类拟,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。
x|y 匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。
[xyz] 字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“p”。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B 匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\d 匹配一个数字字符。等价于[0-9]。
\D 匹配一个非数字字符。等价于[^0-9]。
\f 匹配一个换页符。等价于\x0c和\cL。
\n 匹配一个换行符。等价于\x0a和\cJ。
\r 匹配一个回车符。等价于\x0d和\cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于[^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于\x09和\cI。
\v 匹配一个垂直制表符。等价于\x0b和\cK。
\w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。
\W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。

2 简单使用

  看一个栗子,从一个字符串中查找所有的url,这里为了简单我们只匹配以http或者https开头的,以.com结尾的网址,代码如下,正则表达式是【https?:\/\/([0-9a-z]+\.)+com】,其中【https?】中的?表示前一个字符s出现0或1次;【\/】为转义表示/;【([0-9a-z]+\.)+】中的[0-9a-z]+表示1个或多个小写字母或数字,\.为转义,表示.,综合下来这部分表示格式为xxx.xx的字符串;最后的【com】就表示com:

        static void Main(string[] args)
{
//待匹配的字符串
string content = @"23ftp://haha.cn794http://www.baidu.coml222jjhttps://helloworld.comxxyyhelhttp://blog.cscs.comhelloworld";
//声明url匹配规则对象
Regex regex = new Regex(@"https?:\/\/([0-9a-z]+\.)+com");
MatchCollection matches = regex.Matches(content);
if (matches != null && matches.Count > )
{
foreach (Match match in matches)
{
Console.WriteLine(match.Value);
}
}
Console.ReadKey();
}

  执行结果如下:

3 I 或的使用

  有时候我们的匹配规则不止一种,就要使用到【|】了,如:x|y表示匹配x或者y,(z|f)ood”匹配“zood”或“food”。看一个栗子:

        static void Main(string[] args)
{
//待匹配的字符串
string content = @"xxxhelloxxxxyyyyyworldxxx";
//声明匹配规则对象,并设定匹配规则
Regex regex = new Regex(@"hellox*|worldx+");
//Match match = regex.Match(content);
MatchCollection matches = regex.Matches(content);
if (matches != null && matches.Count > )
{
foreach (Match match in matches)
{
Console.WriteLine(match.Value);
}
}
}

  运行结果如下:

4 非贪婪模式

  上边栗子【hellox*】匹配到helloxxxx,为什么不是匹配到hello或者hellox呢?这是因为*,+,{n,},{n,m}等限定符默认都是重复尽可能多的。如果我们想让重复尽量能少,只需要在限定符的后边加上一个?即可,如*?、+?等,现在我们把上边的栗子改成非贪婪模式:

            //待匹配的字符串
string content = @"xxxhelloxxxxyyyyyworldxxx";
//声明匹配规则对象,并设定匹配规则
Regex regex = new Regex(@"hellox*?|worldx+?");
MatchCollection matches = regex.Matches(content);
if (matches != null && matches.Count > )
{
foreach (Match match in matches)
{
Console.WriteLine(match.Value);
}
}

  运行程序如下:

5 获取分组和非获取分组

  如果我们要一次将邮箱全址、邮箱用户名、邮箱种类都匹配出来就可以用到分组,正则表达式中括号作用是提高优先级和分组。

  如有一个邮箱的正则表达式【([a-zA-Z0-9_]+)@([a-zA-Z0-9]+)\.com】,这里为了简单,邮箱都以.com结尾。这个正则表达式用到了两个括号,这两个括号就是分组,将正则表达式分成了三组,第0组是整个匹配结果,第1组是第一个括号里面的内容(用户名),第二组是第二个括号里面的内容(邮箱类型),我们可以通过Match的Groups对象来访问各个分组。代码如下:

       static void Main(string[] args)
{
//待匹配的字符串
string content = @"wyy@qq.com//www.baidu.yinyue.com^l222/email@163.comjjhelloworld.comxxyyhelblog.cscs.comhelloworld";
//声明匹配规则对象,并设定匹配规则
Regex regex = new Regex(@"([a-zA-Z0-9_]+)@([a-zA-Z0-9]+)\.com");
MatchCollection matches = regex.Matches(content);
foreach (Match match in matches)
{
Console.WriteLine($"完整邮箱:{match.Groups[0].Value},用户名:{match.Groups[1].Value},邮箱类型:{match.Groups[2].Value}");
}
}

  程序运行如下:

  分组是耗费性能的,有时候我们使用括号仅仅只是为了提高优先级,怎么实现在使用括号的同时避免分组呢?这就需要使用非获取分组(?:pattern),我们改写下上边的栗子,不去获取用户名和邮箱类型,只需要在括号内加上【?:】即可,代码如下:

        static void Main(string[] args)
{
//待匹配的字符串
string content = @"wyy@qq.com//www.baidu.yinyue.com^l222/email@163.comjjhelloworld.comxxyyhelblog.cscs.comhelloworld";
//声明匹配规则对象,并设定匹配规则
Regex regex = new Regex(@"(?:[a-zA-Z0-9_]+)@(?:[a-zA-Z0-9]+)\.com");
MatchCollection matches = regex.Matches(content);
foreach (Match match in matches)
{
Console.WriteLine($"完整邮箱:{match.Groups[0]?.Value},用户名:{match.Groups[1]?.Value},邮箱类型:{match.Groups[2]?.Value}");
}
}
}

  程序运行结果如下,可以看到用户名和邮箱类型的分组没有被捕获:

6 正向预查

  有时候我们会遇到这样的需求:在成绩单字符串【班级:1 姓名:张三 性别:男 成绩:100 班级:1 姓名:李四 性别:女 成绩:80 班级:2 姓名:王五 性别:男 成绩:90 班级:2 姓名:赵六 性别:女,成绩:80】中查询所有男生的姓名。我们发现一个规律男生姓名后边的内容都是【 性别:男】,知道这个规律后我们只需要找出后边内容是【 性别:男】的单词就可以了。

  这时就要用到正向预查,正向预查有两种:正向肯定预查(?=pattern)和正向否定预查(?!pattern),针对上边的需求这里使用正向肯定预查,正则表示式为【\b\w+\b(?=\s+性别:男)】,表示查询后边内容式【[空格] 性别:男】的单词,代码如下:

    class Program
{
static void Main(string[] args)
{
//待匹配的字符串
string content = @"班级:1 姓名:张三 性别:男 成绩:100 班级:1 姓名:李四 性别:女 成绩:80 班级:2 姓名:王五 性别:男 成绩:90 班级:2 姓名:赵六 性别:女,成绩:80";
//正向肯定预查,后边内容是【性别:男】的单词就是男生的姓名
Regex regex = new Regex(@"\b\w+\b(?=\s+性别:男)");
MatchCollection matches = regex.Matches(content);
Console.Write("男生名单:");
foreach (Match match in matches)
{
Console.Write($"{match.Value} ");
}
Console.WriteLine();
}
}

  运行程序,结果如下:

  正向否定预查(?!pattern)表示后边的内容不是指定内容,用法和正向肯定预查一样,这里不再演示了。

7 反向预查

  反向预查和正向预查的作用的用法都很类似,正向预查是往后预读,而反向预查则是往前预读。反向预查也分为两种:反向肯定预查(?<=pattern)和反向否定预查(?<!pattern)。

  还是用分析成绩单的栗子,如果需求改成查询班级1的学生姓名该怎么实现呢?我们发现规律:前边的内容是【班级:1 姓名:】的单词就是班级1学生的姓名,所以我们只需要查找前边内容为【班级:1 姓名:】的单词即可,代码如下:

        static void Main(string[] args)
{
//待匹配的字符串
string content = @"班级:1 姓名:张三 性别:男 成绩:100 班级:1 姓名:李四 性别:女 成绩:80 班级:2 姓名:王五 性别:男 成绩:90 班级:2 姓名:赵六 性别:女,成绩:80";
//反向肯定预查,前边的内容是【班级:1 姓名:】就是1班学生的姓名
Regex regex = new Regex(@"(?<=班级:1\s+姓名:)\b\w+\b");
MatchCollection matches = regex.Matches(content);
Console.Write("1班名单:");
foreach (Match match in matches)
{
Console.Write($"{match.Value} ");
}
Console.ReadKey();
}

程序运行如下:

  反向否定预查(?<!pattern)表示前边的内容不是指定内容,用法和反向肯定预查一样,这里不再演示了。

8 开发中遇到的一个小案例

  使用Ueditor的时候把文章以HTML标签的方式存在数据库中,同时要将文章的第一张图片的路径一并存入数据库,所以就需要在Html中获取第一个图片的路径,如果文章没有图片的话则设置一个默认的图片。代码如下:

1.获取html中第一张图片路径的方法:

  /// <summary>
/// 获取第一个图片上传路径
/// </summary>
/// <param name="source">html文本</param>
/// <returns>图片的路径</returns>
public static string GetImageSrcPath(string source)
{
string srcPath = "";
string strRegExPattern = @"<img[^>]+(src)\s*=\s*""?([^ "">]+)""?(?:[^>]+(width|height)\s*=\s*""?([^ "">]+)""?\s+(height|width)\s*=\s*""?([^ "">]+)""?)?(?:[^>]+(alt)\s*=\s*""?([^"">]+)""?)?";
Regex re = new Regex(strRegExPattern, RegexOptions.IgnoreCase);
Match m = re.Match(source);
if (m.Success)
{
srcPath = m.Groups[].Value;
}
string defaultImg = "/ueditor/net/upload/image/20180723/default.jpg";
return string.IsNullOrEmpty(srcPath) ? defaultImg : srcPath;
}

   2.获取html所有图片路径的方法(删除文章同时删除所有的图片时就要用到了)

         /// <summary>
/// 获取所有图片上传路径
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static List<string> GetImgSrcList(string source)
{
List<string> imgSrcList = new List<string>();
string strRegExPattern = @"<img[^>]+(src)\s*=\s*""?([^ "">]+)""?(?:[^>]+(width|height)\s*=\s*""?([^ "">]+)""?\s+(height|width)\s*=\s*""?([^ "">]+)""?)?(?:[^>]+(alt)\s*=\s*""?([^"">]+)""?)?";
Regex re = new Regex(strRegExPattern, RegexOptions.IgnoreCase);
MatchCollection matches = re.Matches(source);
foreach (Match m in matches)
{
imgSrcList.Add(m.Groups[].Value);
} if (imgSrcList.Count == )
{
//一个默认图片
imgSrcList.Add("/ueditor/net/upload/image/20180713/default.jpg");
}
return imgSrcList;

常用正则表达式

用户名 /^[a-z0-9_-]{3,16}$/    3-16位数字字母下划线组成的用户名
密码 /^[a-z0-9_-]{6,18}$/    6-18位数字字母下划线组成的密码
电子邮箱 /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/
URL /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/
IP 地址 /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
手机号码 ^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
国内电话 \d{3}-\d{8}|\d{4}-\d{7}
邮编 [1-9]\d{5}(?!\d)
QQ [1-9][0-9]{4,}
15位身份证 ^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$
18位身份证 ^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$
Unicode编码中的汉字范围 /^[\u2E80-\u9FFF]+$/

 参考文章

  【1】http://tool.oschina.net/uploads/apidocs/jquery/regexp.html

  【2】https://blog.csdn.net/qq_38507850/article/details/79179128

C#获取Html中的图片元素路径的更多相关文章

  1. 获取页面中任意一个元素距离body的偏移量

    //offSet:等同于jQuery中的offSet方法,获取页面中任意一个元素距离body的偏移量function offSet(curEle) { var totalLeft = null; va ...

  2. Android获取SD卡中选中图片的路径(URL)

    最近在做一个图片上传的功能,需要提供上传图片在SD卡中的路径,在网上看了些例子,改改调试成功,代码很简单.其布局文件如下: [html]  view plain copy   <?xml ver ...

  3. c# 应用NPOI 获取Excel中的图片,保存至本地的算法

    要求:读取excel中的图片,保存到指定路径 思路:  利用NPOI中 GetAllPictures()方法获取图片信息 步骤: 1.新建一个Windows窗体应用程序 2.桌面新建一个excel,贴 ...

  4. android 获取SD卡的图片及其路径

    1.首先是intent的设置: private static final int IMAGECODE = 0; Intent imageIntent = new Intent(Intent.ACYIO ...

  5. 爬虫的原理获取html中的图片到本地

    如果你想获取哪个网页的图片,如果你想知道那个网址的美女,还等什么.代码走起:下载即可使用 完成这次瞎爬的原理如下: 第一步:获取html内容 * 第二步:然后在获取的html文本中寻找图片,根据htm ...

  6. Java 获取Word中指定图片的坐标位置

    本文介绍通过Java程序获取Word文档中指定图片的坐标位置. 程序运行环境: Word测试文档:.docx 2013 Free Spire.doc.jar 3.9.0 IntelliJ IDEA J ...

  7. python获取数组中最多的元素

    获取数组中数量最多的元素,也就是最频繁的那个元素,方法有很多,下面是3种最简单的: 用max函数 sample = [1,2,3,3,3,4,5,5] max(set(sample), key=sam ...

  8. Vue.js中的图片引用路径问题

    当我们在Vue.js项目中引用图片时,关于图片路径有以下几种情形: 使用一: 在data里面定义好图片路径: /*错误写法*/ imgUrl:'../assets/logo.png' 在templat ...

  9. c#获取数组中最大的元素

    , , , , , , , , , }; var max = array.Max();//获取数组中的最大值 第一种 //第二种方法 ]; ; i < array.Length; i++) { ...

随机推荐

  1. (转)vmware下给linux虚拟机扩容

    “Well, here’s another fine mess you’ve gotten me into” Let us pretend that you have an Ubuntu Server ...

  2. ABP框架学习

    一.总体与公共结构 1,ABP配置 2,多租户 3,ABP Session 4,缓存 5,日志 6,设置管理 7,Timing 8,ABPMapper 9,发送电子邮件 二.领域层 10,实体 11, ...

  3. [转载]使用VS2015搭建Lua开发环境

    参考原文请看: Lua学习笔记1:Windows7下使用VS2015搭建Lua开发环境(一) Lua学习笔记2:Windows7下使用VS2015搭建Lua开发环境(二) 本篇主要分以下几个部分: 一 ...

  4. 自定义git忽略规则

    输入命令 >a.o git status 此时我想让git忽略这个文件的更新 输入命令 > .gitignore echo "a.o" >> .gitign ...

  5. 【HDU1219】AC Me(水题)

    BUPT2017 wintertraining(16) #4 A HDU1219 题意 多组样例,每组给一行,输出该行各字母个数,每组输出之间输出空行 代码 #include <cstdio&g ...

  6. Domino 邮箱服务器接收不存在的邮箱账号的邮件

    背景: domino邮箱服务器需要设置多个邮件账号邮件转到同一个邮箱账号. 比如:现在没有了 abc@mail.com 的邮箱账号.但是当用户发邮件给它的时候就发给Support@mail.com 原 ...

  7. 自学Aruba5.3.3-Aruba安全认证-有PEFNG 许可证环境的认证配置Captive-Portal

    点击返回:自学Aruba之路 自学Aruba5.3.3-Aruba安全认证-有PEFNG 许可证环境的认证配置Captive-Portal 1. Captive-Portal认证配置前言 1.1 新建 ...

  8. 【Luogu3803】多项式乘法FFT(FFT)

    题目戳我 一道模板题 自己尝试证明了大部分... 剩下的还是没太证出来... 所以就是一个模板放在这里 以后再来补东西吧.... #include<iostream> #include&l ...

  9. 洛谷 P3871 [TJOI2010]中位数 解题报告

    P3871 [TJOI2010]中位数 题目描述 给定一个由N个元素组成的整数序列,现在有两种操作: 1 add a 在该序列的最后添加一个整数a,组成长度为N + 1的整数序列 2 mid 输出当前 ...

  10. Codeforces-gym-101020 problem C. Rectangles

    题目链接:http://codeforces.com/gym/101020/problem/C C. Rectangles time limit per test 2.0 s memory limit ...