1

C# 正则表达式常用的符号和模式解析 - 橙子家

 1 year ago
source link: https://www.cnblogs.com/czzj/p/RegularExpression.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.



〇、正则表达式的基本语法符号

若只简单匹配固定字符串,则无需任何修饰符,例如:需要匹配字符串 77,则可直接写:new Regex("77")

下边例举一下常用的符号:(知道下面这些,一般的正则表达式便可清晰异常)

符号   释义   示例 1   示例 2
\

转义字符,互相转换一个具有特殊功能的字符 和一个普通字符

希望在字符串中至少有一个“\”,那么正则表达式应该这么写:\\+
^......$

开始标记(^)和结束标记($),中间为具体内容

若没有边界,则表示匹配可在字符中匹配

/^AA$/【解析】字符串‘AA’可匹配;‘AAA’不可匹配

/AA$/【解析】取消开始符号‘^’则‘AAA’可匹配,表示以‘AA’结尾

*  、  + 、  ?     指定匹配子表达式的次数

* : 零次或多次;

+ : 一次或多次;

? : 零次或一次

[xxxx]、[^xxxx]

中括号,代表可选择的字符集合,可为任意字符

加了 ^ 后,相反,不可选择的字符集合

[qw12]【解析】代表出现(q、w、1、2)中的字符均满足条件

[A-Za-z0-9]【解析】数字+26个英文字母

[^qw12]【解析】增加符号‘^’,意思与‘示例 1’中的意思相反,标识不能出现(q、w、1、2)中的字符
{m,n}

大括号,匹配数量,代表可匹配 m~n 次连续字符,

另外‘,n’可省略

a{2}【解析】出现‘aa’,例如‘123aaf4’可匹配 a{2,}【解析】匹配2~∞次字符‘a’,即aa、aaa、aaaa......
.

匹配除“/n”之外的任何 单个字符

(pattern)、(?:pattern)、(?=pattern)、(?!pattern)

(pattern):匹配 pattern 并获取;(?:pattern):匹配但不获取

(?=pattern):正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串 (?!pattern):负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串
(xxx){n}

小括号,代表分组,即‘xxx’可出现 n 次

(12|34){2}【解析】匹配1212、1234、3412、3434
xxx|xx 竖线,选择表达式 123|234【解析】代表匹配‘123’或者‘234’  
\数字 反斜线+数字,引用,数字代表引用前面第几个捕获分组 <([a-z]+)><\/\1>【解析】引用第一个捕获分组,可匹配‘<div></div>’  
\d       \D 匹配数字字符,0~9(相反 \D 代表非数字)    
\f    \n    \r \f :匹配换页符 \n:匹配换行符 \r:匹配回车符
\s    \S \s:匹配任何空白字符,包括空格、制表符、换页符等 \S:匹配任何非空白字符  
\w    \W \w:匹配包括下划线的任何单词字符,等价于:[A-Za-z0-9_] \W:等价于:[^A-Za-z0-9_]  
\t 匹配一个制表符    

一、Regex 类简介

出自程序集:System.Text.RegularExpressions.dll。

1. Match 常用的两个静态重载

public static System.Text.RegularExpressions.Match Match (string input, string pattern);
public static System.Text.RegularExpressions.Match Match (string input, string pattern, RegexOptions options);

RegexOptions 枚举中常用的三个:

  IgnoreCase 表示不区分输入的大小写;

  IgnorePatternWhitespace 表示去掉模式中的非转义空白,并启用由#标记的注释;

  RightToLeft 表示从右向左扫描、匹配,这时,静态的Match方法返回从右向左的第一个匹配;

下边是应用实例:(写法一对应定义中的参数)

string inputstr = "ADDR=1234;NAME=ZHANG;PHONE=6789";
{// 写法一
    Match match1 = Regex.Match(inputstr, "NAME=(.+);");
    string value1 = match1.Groups[1].Value;
    // ZHANG;PHONE=6789;NAME=ZHENG
}
inputstr = "ADDR=1234;NAME=ZHANG;PHONE=6789;NAME=ZHENG;";
{// 写法二
    Regex reg = new Regex("NAME=(.+);");
    Match match2 = reg.Match(inputstr);
    string value2 = match2.Groups[1].Value;
    // ZHANG
}
inputstr = "ADDR=1234;name=ZHANG;PHONE=6789";
{// 测试不区分大小写
    Match match3 = Regex.Match(inputstr, "NAME=(.+);", RegexOptions.IgnoreCase);
    string value3 = match3.Groups[1].Value;
    // ZHANG
    Match match31 = Regex.Match(inputstr, "NAME=(.+);");
    string value31 = match31.Groups[1].Value;
    // ""
}
inputstr = "ADDR=1234;NAME=ZHANG;PHONE=6789";
{// 去掉模式中的非转义空白
    Match match4 = Regex.Match(inputstr, " N A ME = (.+) ;", RegexOptions.IgnorePatternWhitespace);
    string value4 = match4.Groups[1].Value; // pattern 中的空格在匹配时被忽略
    // ZHANG
    Match match41 = Regex.Match(inputstr, " N AME=(.+);");
    string value41 = match41.Groups[1].Value;
    // ""
}
inputstr = "ADDR=1234;NAME=ZHANG;;PHONE=6789;ADDR=1234;NAME=ZHANG;";
{// 从右向左扫描、匹配
    Match match5 = Regex.Match(inputstr, ";NAME", RegexOptions.RightToLeft);
    int value5 = match5.Groups[1].Index;
    // 42
    Match match51 = Regex.Match(inputstr, ";NAME");
    int value51 = match51.Groups[1].Index;
    // 9
}

2. Matchs 静态方法

Matchs 方法的匹配规则类似 Match,只是返回的为 MatchCollection。如下示例:

string line = "ADDR=1234;NAME=ZZHANG;NAME=ZZHENG;PHONE=6789;NAME=";
{
    var matches = Regex.Matches(line, "NAME=(.{4})");
    foreach(Match match in matches)
    {
        string value1 = match.Groups[1].Value;
        // ZZHA
        // ZZHE
    }
}

  

1868241-20221222183617128-972280693.png

3. IsMatch 静态方法

以下是两个常用的重载:

public static bool IsMatch (string input, string pattern);
public static bool IsMatch (string input, string pattern, System.Text.RegularExpressions.RegexOptions options);

此方法返回一个 bool,重载形式同静态的 Matches,若输入中匹配模式,返回 true,否则返回 false。

string inputstr = "ADDR=1234;NAME=ZZHANG;NAME=ZZHENG;PHONE=6789;NAME=";
{
    var ismatch1 = Regex.IsMatch(inputstr, "NAME=(.{4})"); // true
    var ismatch2 = Regex.IsMatch(inputstr, "NAME=(.{400})"); // false
}

二、常用示例

在使用正则表达式前,需先引用命名空间:

using System.Text.RegularExpressions;

传入字符串类型的金额进行判断,若不是金额返回报错提示:

string pattern = @"^([1-9]\d{0,9}|0)(\.\d{1,2})?$"; // 两位小数
// 若需要匹配更多位数小数,则可修改“\d{1,2}”中的数字 2
if (!Regex.IsMatch(jine, pattern))
	return "金额格式有误,请重新输入!" ;

解析:^([1-9]\d{0,9}|0)(\.\d{1,2})?$

小数点前:其中 ([1-9]\d{0,9}|0) 中的第一位“[1-9]”代表为 1~9 的数字;“\d{0,9}” 代表一串 0~9 的数字,不限位数;竖线“|”代表前后存在其一,后边是 0,代表可以为小于 1 的小数。

小数点后:其中 (\.\d{1,2})? 问号表示此部分可省,第一位“[1-9]”代表为 1~9 的数字;“\d”代表数字,后边的“{1,2}”表示有 1~2 位小数。

其他常用的数值模式:

0 或非 0 开头的数字 ^(0|[1-9][0-9]*)$
正整数 ^[1-9]\d*$
浮点数 ^(-?\d+)(\.\d+)?$
正数/负数/小数 ^(\-|\+)?\d+(\.\d+)?$

2. 电子邮箱(不允许存在连续的两个点或两个减号)

邮箱地址分为两个部分,@ 符号前和后。前一部分代表用户名,后边是电子邮件服务器的域名。

用户名:可以是字母、数字、点号、减号、下划线,但必须以数字或字母开头,3~18 个字符;

域名规范:只能使用英文字母(a~z,不区分大小写)、数字(0~9)以及连接符(-);连接符(-)不能连续出现、单独注册,也不能放在开头和结尾。

由于域名的种类太多了,因此本模块只简单校验以上条件。

string inputstr = "[email protected]";
{
    var ismatch1 = Regex.IsMatch(inputstr, @"^([\w-\.]+)@([a-zA-Z0-9-\.]+)(\.[a-zA-Z0-9]+)$"); // true
    inputstr = "[email protected]";
    ismatch1 = Regex.IsMatch(inputstr, @"^((?!.*?\.\.)[\w-\.]+)@([a-zA-Z0-9-\.]+)(\.[a-zA-Z0-9]+)$"); // false
    ismatch1 = Regex.IsMatch(inputstr, @"^((?!.*?--)[\w-\.]+)@([a-zA-Z0-9-\.]+)(\.[a-zA-Z0-9]+)$"); // true
    inputstr = "[email protected]";
    ismatch1 = Regex.IsMatch(inputstr, @"^((?!.*?(--|\.\.))[\w-\.]+)@((?!.*?(--|\.\.))[a-zA-Z0-9-\.]+)(\.[a-zA-Z0-9]+)$"); // false
    ismatch1 = Regex.IsMatch(inputstr, @"^((?!.*?--)[\w-\.]+)@([a-zA-Z0-9-\.]+)(\.[a-zA-Z0-9]+)$"); // false
    // 最后一个最为准确
    ismatch1 = Regex.IsMatch(inputstr, @"^[a-zA-Z0-9]((?!.*?(\.\.|--))[a-zA-Z0-9\._-]){1,16}[a-zA-Z0-9]@([0-9a-zA-Z][0-9a-zA-Z-]{0,61}[0-9a-zA-Z]\.)+([0-9a-zA-Z][0-9a-zA-Z-]{0,61}[0-9a-zA-Z])$"); // true
}

由测试结果可以得出结论:

若想简单判断邮件格式,可以用这个:

  ^([\w-\.]+)@([a-zA-Z0-9-\.]+)(\.[a-zA-Z0-9]+)$

比较准确判断的话,请用这个:

  ^[a-zA-Z0-9]((?!.*?(\.\.|--))[a-zA-Z0-9\._-]){1,16}[a-zA-Z0-9]@([0-9a-zA-Z][0-9a-zA-Z-]{0,61}[0-9a-zA-Z]\.)+([0-9a-zA-Z][0-9a-zA-Z-]{0,61}[0-9a-zA-Z])$

解析:首先是将长串分为多个小部分,如下:

// 正则表达式详解
^
[a-zA-Z0-9] // 用户名首位
((?!.*?(\.\.|--))[a-zA-Z0-9\._-]){1,16}
[a-zA-Z0-9] // 用户名末位
@
([0-9a-zA-Z] // .分隔的前边 n 段域名的首位
	[0-9a-zA-Z-]{0,61}
	[0-9a-zA-Z]\.)+
([0-9a-zA-Z] // .分隔的最后一段域名的首位
	[0-9a-zA-Z-]{0,61}
	[0-9a-zA-Z]) // .分隔的最后一段域名的末位
$

3. IPv4

IP 的规则很简单,就是:第一位和最后一位数字不能是 0 或 255。

允许 0 补位的模式:^(25[0-4]|2[0-4]\d]|[01]?\d{2}|[1-9])\.(25[0-5]|2[0-4]\d]|[01]?\d?\d)\.(25[0-5]|2[0-4]\d]|[01]?\d?\d)\.(25[0-4]|2[0-4]\d]|[01]?\d{2}|[1-9])$

^
(25[0-4] // 250~254
	|2[0-4]\d] // 200~249
	|[01]?\d{2} // 10~199
	|[1-9] // 1~9
)
\.(25[0-5]|2[0-4]\d]|[01]?\d?\d)
\.(25[0-5]|2[0-4]\d]|[01]?\d?\d)
\.(25[0-4]|2[0-4]\d]|[01]?\d{2}|[1-9])
$

不允许 0 补位的模式:^(25[0-4]|2[0-4]\d]|1\d{2}|[1-9]\d|[1-9])\.(25[0-5]|2[0-4]\d]|1\d{2}|[1-9]\d|[0-9])\.(25[0-5]|2[0-4]\d]|1\d{2}|[1-9]\d|[0-9])\.(25[0-4]|2[0-4]\d]|1\d{2}|[1-9]\d|[1-9])$

^
(25[0-4] // 250~254
	|2[0-4]\d] // 200~249
	|1\d{2} // 100~199
	|[1-9]\d // 10~99
	|[1-9] // 1~9
)
\.(25[0-5]|2[0-4]\d]|1\d{2}|[1-9]\d|[0-9])
\.(25[0-5]|2[0-4]\d]|1\d{2}|[1-9]\d|[0-9])
\.(25[0-4]|2[0-4]\d]|1\d{2}|[1-9]\d|[1-9])
$

4. 固定电话

3 位或 4 位区号;区号可以用小括号括起来;区号可以省略;区号与本地号间可以用减号或空格隔开;本地号首位不为 0;可以有3位数的分机号,分机号前要加减号。

string inputstr = "(0290)-89898989-666";
{
    var ismatch1 = Regex.IsMatch(inputstr, @"^((\(0\d{2,3}\)|0\d{2,3})[- ])?[1-9]\d{7}(-\d{3})?$"); // true
}

最佳的模式:^((\(0\d{2,3}\)|0\d{2,3})[- ])?[1-9]\d{7}(-\d{3})?$

^
(
  (\(0\d{2,3}\) // 允许区号用小括号包裹
   |0\d{2,3})
  [- ] // 区号和本机号用 - 或空格隔开
)?
[1-9]\d{7}
(-\d{3})?
$

5. 手机号码

本次只识别国内的电话号码,国际区号为 (+86),可以整体省略,也可以单独去掉加号或括号。

在根据国内最新的手机号编码进行测试:

string inputstr = "17797797997";
var ismatch1 = Regex.IsMatch(inputstr, @"^((\+)?86|\((\+)?86\))?1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$"); // true

经测试得出如下模式:

  ^((\+)?86|\((\+)?86\))?1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$

^
((\+)?86|\((\+)?86\))? // 是否添加国际区号
1 // 1 开头
(
   3[0-9]
  |4[01456879]
  |5[0-35-9]
  |6[2567]
  |7[0-8]
  |8[0-9]|
  9[0-35-9])
\d{8} // 后八位随机
$

手机号的最新编码,参考: 手机号验证最新正则表达式

6. 邮政编号

以数字 0 开头的邮编是存在的,比如内蒙古自治区呼和浩特市的 010000,所以对于邮编的六位,没有区别。

因此,邮编的模式就是:

  ^\d{6}$

测试只包含域名地址:

string inputstr = "https://www.baidu.com/?tn=88093251_72_hao_pg";
var ismatch1 = Regex.IsMatch(inputstr, @"^((file|gopher|news|nntp|telnet|ftp|http|https|ftps|sftp)://)?(www\.)?(([a-zA-Z0-9\._-]+\.[a-zA-Z]{2,6}))(/[a-zA-Z0-9\&%_\./-~-]*)?$"); // true

测试可用的模式为:

  ^((file|gopher|news|nntp|telnet|ftp|http|https|ftps|sftp)://)?(www\.)?(([a-zA-Z0-9\._-]+\.[a-zA-Z]{2,6}))(/[a-zA-Z0-9\&%_\./-~-]*)?$

解析:

^
((file|gopher|news|nntp|telnet|ftp|http|https|ftps|sftp)://)?
(www\.)?([a-zA-Z0-9\._-]+\.[a-zA-Z]{2,6})
(/[a-zA-Z0-9\&%_\./-~-]*)?
$

 注:其中第三行表示的是域名地址,可以参考本章节中的“3. IPv4”将 IP 地址兼容。

8. 身份证号

身份证号的规则:

  

1868241-20221228164348713-1929064691.png

地址码:长度 6 位,以不为 0 的数字开头。即:^[1-9]\d{5}$。

年份:一般以 18、19、20 开头,即:^(18|19|20)\d{2}$。

月份:1~9 月需要补 0 ,即:^((0[1-9])|(1[0-2]))$。

日期:1~31 ,即^((0[1-9]|[1-2][0-9])|30|31)$。

顺序码:3 位数字,即:^\d{3}$。

校验码:1位数字或字母X或x,即^[0-9Xx]$。

// 测试
string inputstr = "11010519491231002X";
var ismatch1 = Regex.IsMatch(inputstr, @"^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))((0[1-9]|[1-2][0-9])|30|31)\d{3}[0-9Xx]$"); // true

测试结果:

  ^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))((0[1-9]|[1-2][0-9])|30|31)\d{3}[0-9Xx]$ 

  参考: 身份证号码的正则表达式及验证详解

9. 经纬度

经度:-180.0~+180.0(整数部分为 0~180,必须输入 1 到 5 位小数)

  ^[\-\+]?(0?\d{1,2}\.\d{1,5}|1[0-7]?\d{1}\.\d{1,5}|180\.0{1,5})$

^
[-\+]?
(
 0?\d{1,2}\.\d{1,5}
 |1[0-7]?\d{1}\.\d{1,5}
 |180\.0{1,5} // 可代表 180.00000
)

纬度:-90.0~+90.0(整数部分为 0~90,必须输入 1 到 5 位小数)

  ^[\-\+]?([0-8]?\d{1}\.\d{1,5}|90\.0{1,5})$

^
[-\+]?
(
 [0-8]?\d{1}\.\d{1,5}
 |90\.0{1,5} // 可代表:90.00000
)
$

  参考:C# 正则表达式大全       正则表达式教程——语法篇

注:暂时整理这些,欢迎补充和指正。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK