正则表达式
正则表达式(Regular expression) 是一种通用的字符串匹配模式,我更喜欢把它说成是一种语法。
一般用于如下操作:
- 用来检测目标字符串是否“包含”特定字符 -----(屏蔽字等)
- 用来检测目标字符串是否“匹配”特定规则 ----- (ip地址,账号密码)
- 用来“捕获”满足条件的语句 ---------------(协议交互,关键数据提取)
- 用来将匹配的字符串进行“替换” ------------ (版本号,敏感词替换成*)
常见关键字
特别字符 | 描述 |
^ |
1.匹配字符串开头位置 2.放在括号中表示不接受xxx字符 |
$ | 1.匹配文本末尾 |
() | 子表达式范围 |
* | 0次或多次 等价于 {0,} |
+ | 1次或多次 等价于 {1,} |
? | 0次或1次 等价于 {0,1} |
. | 除\n以外任意单字符 |
[] | 中括号表达式(一般是取值范围) |
{} | 限定符表达式(一般为次数限定) |
| | 或 |
{n} | n是一个非负数 匹配确定n次 |
{n,} | n是一个非负数 至少匹配n次 |
{n,m} | n&m是一个非负数 m >= n ,至少匹配n次 至多匹配m次 |
?= | 捕获断言前匹配的内容 (尾缀匹配) |
?!x | 负向捕获(尾缀匹配 很少用) |
?<=x | 捕获断言后匹配内容(前缀匹配) |
?<!x | 负向捕获 (前缀匹配 很少用) |
\w | 匹配字母 数字 下划线 等价于[A-Za-z0-9_] |
\s | 匹配任何空白字符包括空格、制表符、换行等[\f\n\r\t\v] |
\S | 匹配任何非空白字符 |
事例 PS (验证函数见完整版代码)
------ 账号验证 (格式匹配)------
- 以“大/小写字母”开头
- 只允许使用“大/小写字母”“阿拉伯数字”
- 文本长度必须在 5 - 12 之间
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 账号验证 *1.以 "大/小写字母" 开头 *2.除开头以外只能存在 “大 / 小写字母” “阿拉伯数字” *3.文本长度必须在5 - 12 */ string testStr0 = "jw328791554"; string testStr1 = "dasd"; string testStr2 = "1jwhjkadhksa"; string testStr3 = "jiangweio3778913123"; string testStr4 = "Jw32tason3"; Regex rgx = new Regex(@"^[a-zA-Z][a-zA-Z0-9]{5,12}$"); RegexMatchTest(testStr0, rgx); RegexMatchTest(testStr1, rgx); RegexMatchTest(testStr2, rgx); RegexMatchTest(testStr3, rgx); RegexMatchTest(testStr4, rgx);
----- 密码验证 (格式匹配) ------
- 不能为纯数字
- 不能为纯字母
- 长度必须在 6 - 20 之间
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 密码验证 * 1.不能为纯数字 * 2.不能为纯字母 * 3.长度必须在 6 - 20 * * ?! 表示 “负向预查” 任何不匹配的字符串 */ string testStr5 = "3213123"; string testStr6 = "dsadsaddsadasd"; string testStr7 = "jwJw381"; string testStr8 = "我的大鲵"; string testStr9 = "01sd10"; Regex rgx2 = new Regex(@"^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$"); RegexMatchTest(testStr5, rgx2); RegexMatchTest(testStr6, rgx2); RegexMatchTest(testStr7, rgx2); RegexMatchTest(testStr8, rgx2); RegexMatchTest(testStr9, rgx2);
----- 手机号码验证 (格式匹配)-----
- 全数字
- 1开头的11位数字
- 第二位为[34578]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * 手机号码验证 * 1.全部为数字 * 2.1 开头 的 11位数字 * 3.第二位在 [34578] */ string testStr10 = "15928517727"; string testStr11 = "_110"; Regex rgx3 = new Regex(@"1[34578]\d{9}$"); RegexMatchTest(testStr10, rgx3); RegexMatchTest(testStr11, rgx3);
----- 是否包含中文 (格式匹配) -----
- 范围匹配
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * 是否包含中文 * 1.[\x4e00 - \x9fa5]+ */ string testStr12 = "jiangwei将"; string testStr13 = "蒋伟"; string testStr14 = "j将 _ 为"; string testStr15 = "vvvvv"; Regex rgx4 = new Regex(@"[\u4e00-\u9fa5]+"); RegexMatchTest(testStr12, rgx4); RegexMatchTest(testStr13, rgx4); RegexMatchTest(testStr14, rgx4); RegexMatchTest(testStr15, rgx4);
----- 敏感词匹配 (格式匹配)-----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * 敏感词 匹配 * | 用于取或 */ string testStr16 = "蒋伟珠海妮李小满薛菡岳圆Def"; Regex rgx5 = new Regex("(大侠们)+"); Regex rgx6 = new Regex("(大侠们|薛菡)+"); RegexMatchTest(testStr16, rgx5); RegexMatchTest(testStr16, rgx6);
----- 敏感词替换 (文本替换 )-----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//敏感词 替换 string testStr31 = "我支持香港警察,好了,你们可以打我了!<舆论暴徒,记者>"; Regex rgx23 = new Regex(@"舆论压力|香港警察"); Regex rgx24 = new Regex(@"记者|牛逼"); string temp = rgx23.Replace(testStr31, "****"); temp = rgx24.Replace(temp, "**"); Debug.Log(temp);
----- 字符串过滤 (格式匹配)-----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * 过滤字符串数组 */ string[] filePaths = new string[] { "jw0.data", "jw1.data", "jw1_1.data", "jw1_44.data", "jw45", "yy45.data", "libray.txt", "jwjw213", "jwjw341_3.data","jw34.data"}; Regex rgx7 = new Regex(@".*\.data");//过滤所有的.data文件 //string[] temp = RegexScreen(filePaths, rgx7); Regex rgx8 = new Regex(@"^jw.*\.data");//过滤所有的jw*.data文件 //string[] temp = RegexScreen(filePaths, rgx8); Regex rgx9 = new Regex(@"^jw[0-9]+\.data");//过滤所有jw开头接着只有数字以.data结尾的文件 RegexScreen(filePaths, rgx9);
----- Ipv4 ip地址匹配 (格式匹配)-----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * 1. IPv4地址匹配 * \d{1,3}(.\d{1,3}){3}) * * 这里仅仅是试试“捕获组”,并不是真正意义上的捕获 * 这里的捕获更多是一种特殊形式的文本简写,列入下列表达式可以 * 特殊匹配4个相同数字的ip地址格式,因为这里\1捕获的是1号(0号位为表达式本身)的文本数据 * (\d{1,3,})(.\1){3} */ string testStr17 = "192.168.1.2"; string testStr18 = "192.168.256.333"; string testStr19 = "localhost"; Regex rgx10 = new Regex(@"\d{1,3}(.\d{1,3}){3}"); RegexMatchTest(testStr17, rgx10); RegexMatchTest(testStr18, rgx10); RegexMatchTest(testStr19, rgx10);
----- 协议长度捕获 (文本捕获) -----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * 协议长度捕获(非捕获组 常用类型捕获 零宽度断言) * 1.?=x 捕获断言前匹配内容 (尾缀匹配) * 2.?!x 负向捕获 (很少用) (尾缀匹配) * 3.?<=x 捕获断言后匹配内容 (前缀匹配) * 4. ?<!x 负向捕获 (很少用) (前缀匹配) * eg0:以一定格式进行区分 如 [Length=xxx]xxxxx */ string testStr20 = "product_path"; Regex rgx12 = new Regex(@"(\w+)(?=_path)"); RegexCatchTest(testStr20, rgx12); string testStr21 = "product_path,jiangwei_path"; Regex rgx13 = new Regex(@"(\w+)(?=_path)"); RegexCatchTest2(testStr21, rgx13); string testStr22 = @"[Length=17]jiangweiasdasd"; Regex rgx14 = new Regex(@"(?<=\[Length=)(\d+)(?=\])"); RegexCatchTest(testStr22, rgx14); string testStr23 = @"[Length=17]jiangweiasdasd[Length=21]dasda[lengt= 13"; Regex rgx15 = new Regex(@"(?<=\[Length=)(\d+)(?=\])"); RegexCatchTest2(testStr23, rgx15);
----- 数字截断 浮点数截断 (文本捕获) -----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * 数字截断 */ string testStr24 = "3.1415926"; Regex rgx16 = new Regex(@"^\d+\.\d{1,3}"); RegexCatchTest(testStr24, rgx16);
----- 大小写 容差 (修正符) -----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * 修正符 * 以?开始的修正符 * (?!) 表示后面所有字符开启不区分大小写模式 (暂未测试成功) * (?!:x) 单x不区分大小写 * */ string testStr25 = "Ab"; string testStr26 = "AB"; Regex rgx17 = new Regex("(?!:a)b"); Regex rgx20 = new Regex("(?!:ab)"); RegexMatchTest(testStr25, rgx17); RegexMatchTest(testStr26, rgx17); RegexMatchTest(testStr25, rgx20); RegexMatchTest(testStr26, rgx20);
----- 截断测试 2 (这个忽略掉)-----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 截断测试2 */ string testStr27 = "5567"; string testStr28 = "4313145151756655"; Regex rgx18 = new Regex("(?<!4)56(?=7)"); Regex rgx19 = new Regex(@"(?<=4)\d+(?=7)"); RegexCatchTest(testStr27, rgx18); RegexCatchTest(testStr28, rgx19);
----- 空白符删除 (文本替换)-----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* * 替换 (剔除所有空白字符) */ string testStr29 = "<Length=25> dashdkasdhk<Length=24> dasd \r\n"; Regex rgx21 = new Regex(@"\s"); Debug.Log(rgx21.Replace(testStr29, ""));
----- 版本号替换 (文本替换) -----
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//版本号 替换 string testStr30 = "static public string BUILD_VERSION = 1.0; SCrore line"; Regex rgx22 = new Regex(@"(?<=BUILD_VERSION\s?=\s?).*(?=;)"); Debug.Log(rgx22.Replace(testStr30, "2.0"));
完整版代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using UnityEngine; using System; using System.Text.RegularExpressions; using System.Collections.Generic; public class JwTest : MonoBehaviour { void Start () { /* 账号验证 *1.以 "大/小写字母" 开头 *2.除开头以外只能存在 “大 / 小写字母” “阿拉伯数字” *3.文本长度必须在5 - 12 */ string testStr0 = "jw328791554"; string testStr1 = "dasd"; string testStr2 = "1jwhjkadhksa"; string testStr3 = "jiangweio3778913123"; string testStr4 = "Jw32tason3"; Regex rgx = new Regex(@"^[a-zA-Z][a-zA-Z0-9]{5,12}$"); //RegexMatchTest(testStr0, rgx); //RegexMatchTest(testStr1, rgx); //RegexMatchTest(testStr2, rgx); //RegexMatchTest(testStr3, rgx); //RegexMatchTest(testStr4, rgx); /* 密码验证 * 1.不能为纯数字 * 2.不能为纯字母 * 3.长度必须在 6 - 20 * * ?! 表示 “负向预查” 任何不匹配的字符串 */ string testStr5 = "3213123"; string testStr6 = "dsadsaddsadasd"; string testStr7 = "jwJw381"; string testStr8 = "我的大鲵"; string testStr9 = "01sd10"; Regex rgx2 = new Regex(@"^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$"); //RegexMatchTest(testStr5, rgx2); //RegexMatchTest(testStr6, rgx2); //RegexMatchTest(testStr7, rgx2); //RegexMatchTest(testStr8, rgx2); //RegexMatchTest(testStr9, rgx2); /* * 手机号码验证 * 1.全部为数字 * 2.1 开头 的 11位数字 * 3.第二位在 [34578] */ string testStr10 = "15928517727"; string testStr11 = "_110"; Regex rgx3 = new Regex(@"1[34578]\d{9}$"); //RegexMatchTest(testStr10, rgx3); //RegexMatchTest(testStr11, rgx3); /* * 是否包含中文 * 1.[\x4e00 - \x9fa5]+ */ string testStr12 = "jiangwei将"; string testStr13 = "蒋伟"; string testStr14 = "j将 _ 为"; string testStr15 = "vvvvv"; Regex rgx4 = new Regex(@"[\u4e00-\u9fa5]+"); //RegexMatchTest(testStr12, rgx4); //RegexMatchTest(testStr13, rgx4); //RegexMatchTest(testStr14, rgx4); //RegexMatchTest(testStr15, rgx4); /* * 敏感词 匹配 * | 用于取或 */ string testStr16 = "蒋伟珠海妮李小满薛菡岳圆Def"; Regex rgx5 = new Regex("(大侠们)+"); Regex rgx6 = new Regex("(大侠们|薛菡)+"); //RegexMatchTest(testStr16, rgx5); //RegexMatchTest(testStr16, rgx6); /* * 过滤字符串数组 */ string[] filePaths = new string[] { "jw0.data", "jw1.data", "jw1_1.data", "jw1_44.data", "jw45", "yy45.data", "libray.txt", "jwjw213", "jwjw341_3.data","jw34.data"}; Regex rgx7 = new Regex(@".*\.data");//过滤所有的.data文件 //string[] temp = RegexScreen(filePaths, rgx7); Regex rgx8 = new Regex(@"^jw.*\.data");//过滤所有的jw*.data文件 //string[] temp = RegexScreen(filePaths, rgx8); Regex rgx9 = new Regex(@"^jw[0-9]+\.data");//过滤所有jw开头接着只有数字以.data结尾的文件 RegexScreen(filePaths, rgx9); /* * 1. IPv4地址匹配 * \d{1,3}(.\d{1,3}){3}) * * 这里仅仅是试试“捕获组”,并不是真正意义上的捕获 * 这里的捕获更多是一种特殊形式的文本简写,列入下列表达式可以 * 特殊匹配4个相同数字的ip地址格式,因为这里\1捕获的是1号(0号位为表达式本身)的文本数据 * (\d{1,3,})(.\1){3} */ string testStr17 = "192.168.1.2"; string testStr18 = "192.168.256.333"; string testStr19 = "localhost"; Regex rgx10 = new Regex(@"\d{1,3}(.\d{1,3}){3}"); RegexMatchTest(testStr17, rgx10); RegexMatchTest(testStr18, rgx10); RegexMatchTest(testStr19, rgx10); /* * 协议长度捕获(非捕获组 常用类型捕获 零宽度断言) * 1.?=x 捕获断言前匹配内容 (尾缀匹配) * 2.?!x 负向捕获 (很少用) (尾缀匹配) * 3.?<=x 捕获断言后匹配内容 (前缀匹配) * 4. ?<!x 负向捕获 (很少用) (前缀匹配) * eg0:以一定格式进行区分 如 [Length=xxx]xxxxx */ string testStr20 = "product_path"; Regex rgx12 = new Regex(@"(\w+)(?=_path)"); RegexCatchTest(testStr20, rgx12); string testStr21 = "product_path,jiangwei_path"; Regex rgx13 = new Regex(@"(\w+)(?=_path)"); RegexCatchTest2(testStr21, rgx13); string testStr22 = @"[Length=17]jiangweiasdasd"; Regex rgx14 = new Regex(@"(?<=\[Length=)(\d+)(?=\])"); RegexCatchTest(testStr22, rgx14); string testStr23 = @"[Length=17]jiangweiasdasd[Length=21]dasda[lengt= 13"; Regex rgx15 = new Regex(@"(?<=\[Length=)(\d+)(?=\])"); RegexCatchTest2(testStr23, rgx15); /* * 数字截断 */ string testStr24 = "3.1415926"; Regex rgx16 = new Regex(@"^\d+\.\d{1,3}"); RegexCatchTest(testStr24, rgx16); /* * 修正符 * 以?开始的修正符 * (?!) 表示后面所有字符开启不区分大小写模式 (暂未测试成功) * (?!:x) 单x不区分大小写 * */ string testStr25 = "Ab"; string testStr26 = "AB"; Regex rgx17 = new Regex("(?!:a)b"); Regex rgx20 = new Regex("(?!:ab)"); RegexMatchTest(testStr25, rgx17); RegexMatchTest(testStr26, rgx17); RegexMatchTest(testStr25, rgx20); RegexMatchTest(testStr26, rgx20); /* 截断测试2 */ string testStr27 = "5567"; string testStr28 = "4313145151756655"; Regex rgx18 = new Regex("(?<!4)56(?=7)"); Regex rgx19 = new Regex(@"(?<=4)\d+(?=7)"); RegexCatchTest(testStr27, rgx18); RegexCatchTest(testStr28, rgx19); /* * 替换 (剔除所有空白字符) */ string testStr29 = "<Length=25> dashdkasdhk<Length=24> dasd \r\n"; Regex rgx21 = new Regex(@"\s"); Debug.Log(rgx21.Replace(testStr29, "")); //版本号 替换 string testStr30 = "static public string BUILD_VERSION = 1.0; SCrore line"; Regex rgx22 = new Regex(@"(?<=BUILD_VERSION\s?=\s?).*(?=;)"); Debug.Log(rgx22.Replace(testStr30, "2.0")); //敏感词 替换 string testStr31 = "我支持香港警察,好了,你们可以打我了!<舆论暴徒,记者>"; Regex rgx23 = new Regex(@"舆论压力|香港警察"); Regex rgx24 = new Regex(@"记者|牛逼"); string temp = rgx23.Replace(testStr31, "****"); temp = rgx24.Replace(temp, "**"); Debug.Log(temp); } //验证函数 bool RegexMatchTest(string _source, Regex _rgx) { bool r = false; if (String.IsNullOrEmpty(_source) || _rgx == null) return r; if (_rgx.IsMatch(_source)) { Debug.Log( _source + " Matched " + _rgx.ToString()); return true; } Debug.Log("<color=#ff0000>" + _source + " canot Match " + _rgx.ToString() + "</color>"); return r; } //文件过滤 string[] RegexScreen(string[] _strs, Regex _rgx) { List<string> r = new List<string>(); for (int i = 0; i < _strs.Length; ++i) { if (_rgx.IsMatch(_strs[i])) { r.Add(_strs[i]); Debug.Log("---->" + _strs[i]); } } return r.ToArray(); } //捕获测试(单) string RegexCatchTest(string _str, Regex _rgx) { string r = string.Empty; if (_rgx.IsMatch(_str)) { r = _rgx.Match(_str).Value; Debug.Log("---->" + r); } return r; } //捕获测试(多) string[] RegexCatchTest2(string _str, Regex _rgx) { List<string> rl = new List<string>(); MatchCollection mc = _rgx.Matches(_str); if (mc.Count > 0) { foreach (var v in mc) { rl.Add(v.ToString()); Debug.Log("----->" + v.ToString()); } } return rl.ToArray(); } }