正则表达式平时不常用,经常都是用的时候,临时抱佛脚,查文档,然后就是被各种坑之后,才会逐渐熟练。
在线正则表达式测试:http://tool.oschina.net/regex/
在线JSON格式化:https://www.bejson.com/
正则表达式手册:http://tool.oschina.net/uploads/apidocs/jquery/regexp.html
先来看下代码和运行效果吧
string msg, rex; Match m; msg = "昨日总能耗0度。 (长沙市口腔医院)星期一【紫衡技术】"; rex = @".*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。 \((.*)\)(.{3}).*"; m = Regex.Match(msg, rex); Console.WriteLine("0:" + m.Success); WriteGroupInfo(m); //1 msg = @"上周总能耗28401.4度。 (沙井街道办)星期一【紫衡技术】"; rex = @".*(上周总?能耗)([0-9]{1,}[.][0-9]*)*度。 \((.*)\)(.{3}).*"; //昨日总能耗2582.1度。【长沙市天心区人民法院】2018 - 07 - 08【紫衡技术】 m = Regex.Match(msg, rex); var r = m.Success; Console.WriteLine("1:"+r); WriteGroupInfo(m); //2 rex = @".*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。\【(.*)\】(\d{4}-\d{2}-\d{2}).*"; msg= "昨日总能耗209.9度。【长沙市天心区人民检察院】2018-07-08【紫衡技术】"; Match m1 = Regex.Match(msg, rex); Console.WriteLine("2:"+m1.Success); WriteGroupInfo(m1); //3 rex = @".*(上周总?能耗)([0-9]{1,}[.]?[0-9]*)*度。 \((.*)\)(.{3}).*"; msg = "上周总能耗10922.4度。 (深圳市地方税务局第二稽查局)星期一【紫衡技术】"; m1 = Regex.Match(msg, rex); Console.WriteLine("3:"+m1.Success); WriteGroupInfo(m1); //4 rex = @".*(上月总?能耗)([0-9]{1,}[.]?[0-9]*)*度。 \((.*)\)(.{8}).*"; msg = "上月总能耗49276.9度。 (深圳市地方税务局第二稽查局)2018年06月【紫衡技术】"; m1 = Regex.Match(msg, rex); Console.WriteLine("4:"+m1.Success); WriteGroupInfo(m1); //5 rex = @".*(建筑名称)\:(.*),在(\d{4}-\d{2}-\d{2}).{3}([0-9]{1,}[.][0-9]*)*度。"; msg = "建筑名称:长沙市天心区人民法院,在2018-07-08日用电2582.1度。"; m1 = Regex.Match(msg, rex); Console.WriteLine("5:"+m1.Success); WriteGroupInfo(m1); //6 rex = @"(今日能耗)\:([0-9]{1,}[.]?[0-9]*)"; msg = "今日能耗:300【紫衡技术】"; m1 = Regex.Match(msg, rex); Console.WriteLine("6:" + m1.Success); WriteGroupInfo(m1); //^【([^】]+)】异常(.+?)服务(【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)
//*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*.+ rex = @"^【([^】]+)】异常(.+?)服务(【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*
(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*.+"; msg = "【公司WNC服务监控台】异常 - 服务【Secom.Emx.SmsServer.Service】未找到或者未安装!【紫衡技术】"; m1 = Regex.Match(msg, rex); Console.WriteLine("7:" + m1.Success); WriteGroupInfo(m1); Console.ReadKey(); } private static void WriteGroupInfo(Match m) { var g = m.Groups; if (g.Count > 0) { for (var i = 0; i < g.Count; i++) { Console.WriteLine(i+":"+g[i].Value); } } }
运行结果:
需要注意的地方,待匹配文字中的空格以及全角和半角字符要注意区分。
存储正则表达式字符串,不能存储到Json文件中,特殊字符会出现转义,存XML中没有这个问题。通过构造sql语句存储到mysql中的时候,反斜杠\将会被直接吃掉,所以插入之前要先进行转义。
var _TemplateReg = v.Value.TemplateReg.Replace("\\", "\\\\");
在C#中\\表示\,\\\\就表示\\。
之前在一个全局变量中存储了许多数据,现在我需要将其存储到数据库中。原来的代码如下:
/// <summary> /// 短信模板 /// </summary> #region old code Dictionary<string, SmsTemplate> templates = new Dictionary<string, SmsTemplate> { // 能耗日报模板 { "能耗提醒", new SmsTemplate { TemplateCode = "SMS_139242133", TemplateReg = @"测试短信通知", TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty }, SignName = "紫衡技术" } }, { "测试", new SmsTemplate { TemplateCode = "SMS_119091381", TemplateReg = @"测试短信通知", TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty }, SignName = "紫衡技术" } }, { "能耗", new SmsTemplate { TemplateCode = "SMS_119076277", TemplateReg = @"^[^(上周)|(上月)]*(能耗)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*$", TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty }, SignName = "能耗报告" } }, { "能耗Extend", new SmsTemplate { TemplateCode = "SMS_128880488", TemplateReg = @"^[^(上周)|(上月)]*(能耗)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*$", TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty, extend=string.Empty}, SignName = "能耗报告" } }, { "昨日能耗", new SmsTemplate { TemplateCode = "SMS_139242142", TemplateReg = @".*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。 \((.*)\)(.{3}).*",//昨日总能耗16677.6度。 (天心区鑫远白天鹅酒店)星期一【紫衡技术】 TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty }, SignName = "能耗报告" } }, { "昨日能耗1", new SmsTemplate { TemplateCode = "SMS_139242142", TemplateReg = @".*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。\【(.*)\】(\d{4}-\d{2}-\d{2}).*",//昨日总能耗209.9度。【长沙市天心区人民检察院】2018-07-08【紫衡技术】 TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty }, SignName = "能耗报告" } }, { "上周能耗", new SmsTemplate { TemplateCode = "SMS_119081757", TemplateReg = @".*(上周总?能耗)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*", TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty }, SignName = "能耗报告" } }, { "上月能耗", new SmsTemplate { TemplateCode = "SMS_119086386", TemplateReg = @".*(上月总?能耗)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*", TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty }, SignName = "能耗报告" } }, { "定额", new SmsTemplate { TemplateCode = "SMS_119076277", TemplateReg = @".*(定额)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*", TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty }, SignName = "能耗报告" } }, { "基准", new SmsTemplate { TemplateCode = "SMS_119076277", TemplateReg = @".*(基准)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*", TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty }, SignName = "能耗报告" } }, { "节能量", new SmsTemplate { TemplateCode = "SMS_119076277", TemplateReg = @".*(节能量)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*", TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty }, SignName = "能耗报告" } }, { "优化", new SmsTemplate { TemplateCode = "SMS_119076277", TemplateReg = @".*(优化)值*[::]*([\d.]+).*\(([^)]+)\)(\d{4}-\d{2}-\d{2}).*", TemplateParam = new { name=string.Empty, date=string.Empty, energy=string.Empty }, SignName = "能耗报告" } }, // 报警日报模板 { "报警", new SmsTemplate { TemplateCode = "SMS_119076278", TemplateReg = @"(建筑\[)*(.+?)([\],,])*产生以下报警:(.+)(【紫衡技术】)", TemplateParam = new { name=string.Empty, date=string.Empty, alarm=string.Empty }, SignName = "能管系统报警" } }, // 运维工单模板 { "运维通知", new SmsTemplate { TemplateCode = "SMS_119091206", TemplateReg = "您有一条新的(.+)工单需处理【工单号[::]([^】]+).+", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "运维系统" } }, { "运维抢单", new SmsTemplate { TemplateCode = "SMS_119076276", TemplateReg = "您有一条新的(.+)工单(提示)*【工单号[::]([^】]+).+", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "运维系统" } }, { "运维派单", new SmsTemplate { TemplateCode = "SMS_119076273", TemplateReg = "您有新的(.+)工单无人[抢|接]单【工单号[::]([^】]+).+", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "运维系统" } }, { "库存不足", new SmsTemplate { TemplateCode = "SMS_119091203", TemplateReg = ".+【([^】]+)】.+库存已不足.+", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "运维系统" } }, { "维修签到", new SmsTemplate { TemplateCode = "SMS_119076712", TemplateReg = ".*您有(.*)未签到【工单号:([^】]+)】.+", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "运维系统" } } , { "报警抢单", new SmsTemplate { TemplateCode = "SMS_119091869", TemplateReg = "您有(.*)报警.*无人[抢|接]单【工单号[::]([^】]+).+", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "运维系统" } } , { "广医派工", new SmsTemplate { TemplateCode = "SMS_135795374", TemplateReg = "您有新的(.+)工单(.+)需处理,详情请打开“智慧机电运维系统APP”查看。", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "运维系统" } } , { "报警签到", new SmsTemplate { TemplateCode = "SMS_119081998", TemplateReg = "您有(.*)报警事件未现场签到【工单号[::]([^】]+).+", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "运维系统" } }, { "未处理完崔单", new SmsTemplate { TemplateCode = "SMS_119076997", TemplateReg = "您有(.*)处理尚未完成【工单号[::]([^】]+).+", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "运维系统" } }, { "运维崔单", new SmsTemplate { TemplateCode = "SMS_119087014", TemplateReg = "您有一条(.+)催单提示【工单号[::]([^】]+).+", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "运维系统" } }, { "运维工单事件", new SmsTemplate { TemplateCode = "SMS_119091936", TemplateReg = "您有新的工单事件【工单号[::]([^】]+).+", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "运维系统" } }, { "MAN服务未找到异常", new SmsTemplate { TemplateCode = "SMS_120120306", TemplateReg = "^【([^】]+)】异常(.+?)服务(【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*.+", TemplateParam = new { type=string.Empty, code=string.Empty }, SignName = "能管365" } } }; #endregion
我想直接通过代码来自动将其迁移到mysql数据库中去。
/// <summary> /// 初始化数据,将原来代码中的模板配置生成并加载到数据库中 /// </summary> /// <param name="templates"></param> /// <returns></returns> public int InitData(Dictionary<string, SmsTemplate> templates) { StringBuilder sb = new StringBuilder(); sb.Append("INSERT INTO smstemplate VALUES"); foreach(var v in templates) { var _TemplateReg = v.Value.TemplateReg.Replace("\\", "\\\\"); sb.AppendFormat(@"(\'{0}\',\'{1}\',\'{2}\',\'{3}\',\'{4}\'),",v.Key,v.Value.TemplateCode, _TemplateReg, JsonConvert.SerializeObject(v.Value.TemplateParam),v.Value.SignName); } string sql= sb.ToString().TrimEnd(\',\'); var cmd = db.GetSqlStringCommand(sql); return db.ExecuteNonQuery(cmd); } /// <summary> /// 从数据库中加载模板配置列表 /// </summary> /// <returns>模板配置列表</returns> public Dictionary<string, SmsTemplate> GetSmsTemplate() { Dictionary<string, SmsTemplate> dic = new Dictionary<string, SmsTemplate>(); var sql = "SELECT `Key`,`TemplateCode`,`TemplateReg`,`TemplateParam`,`SignName` FROM smstemplate"; try { var cmd = db.GetSqlStringCommand(sql); SmsTemplate item; string key; using (var reader = db.ExecuteReader(cmd)) { while (reader.Read()) { key = reader.GetString(0); item = new SmsTemplate(); item.TemplateCode = reader.GetString(1); item.TemplateReg = reader.GetString(2); item.TemplateParam = (JObject)JsonConvert.DeserializeObject(reader.GetString(3)); item.SignName = reader.GetString(4); dic.Add(key, item); } } } catch(Exception ex) { throw new Exception(ex.Message); } return dic; }
构造完成后的sql脚本:
INSERT INTO smstemplate VALUES ( \'能耗提醒\', \'SMS_139242133\', \'测试短信通知\', \'{"name":"","date":"","energy":""}\', \'紫衡技术\' ), ( \'测试\', \'SMS_119091381\', \'测试短信通知\', \'{"name":"","date":"","energy":""}\', \'紫衡技术\' ), ( \'能耗\', \'SMS_119076277\', \'^[^(上周)|(上月)]*(能耗)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*$\', \'{"name":"","date":"","energy":""}\', \'能耗报告\' ), ( \'能耗Extend\', \'SMS_128880488\', \'^[^(上周)|(上月)]*(能耗)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*$\', \'{"name":"","date":"","energy":"","extend":""}\', \'能耗报告\' ), ( \'昨日能耗\', \'SMS_139242142\', \'.*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。 \\((.*)\\)(.{3}).*\', \'{"name":"","date":"","energy":""}\', \'能耗报告\' ), ( \'昨日能耗1\', \'SMS_139242142\', \'.*(昨日总?能耗)([0-9]{1,}[.]?[0-9]*)*度。\\【(.*)\\】(\\d{4}-\\d{2}-\\d{2}).*\', \'{"name":"","date":"","energy":""}\', \'能耗报告\' ), ( \'上周能耗\', \'SMS_119081757\', \'.*(上周总?能耗)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*\', \'{"name":"","date":"","energy":""}\', \'能耗报告\' ), ( \'上月能耗\', \'SMS_119086386\', \'.*(上月总?能耗)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*\', \'{"name":"","date":"","energy":""}\', \'能耗报告\' ), ( \'定额\', \'SMS_119076277\', \'.*(定额)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*\', \'{"name":"","date":"","energy":""}\', \'能耗报告\' ), ( \'基准\', \'SMS_119076277\', \'.*(基准)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*\', \'{"name":"","date":"","energy":""}\', \'能耗报告\' ), ( \'节能量\', \'SMS_119076277\', \'.*(节能量)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*\', \'{"name":"","date":"","energy":""}\', \'能耗报告\' ), ( \'优化\', \'SMS_119076277\', \'.*(优化)值*[::]*([\\d.]+).*\\(([^)]+)\\)(\\d{4}-\\d{2}-\\d{2}).*\', \'{"name":"","date":"","energy":""}\', \'能耗报告\' ), ( \'报警\', \'SMS_119076278\', \'(建筑\\[)*(.+?)([\\],,])*产生以下报警:(.+)(【紫衡技术】)\', \'{"name":"","date":"","alarm":""}\', \'能管系统报警\' ), ( \'运维通知\', \'SMS_119091206\', \'您有一条新的(.+)工单需处理【工单号[::]([^】]+).+\', \'{"type":"","code":""}\', \'运维系统\' ), ( \'运维抢单\', \'SMS_119076276\', \'您有一条新的(.+)工单(提示)*【工单号[::]([^】]+).+\', \'{"type":"","code":""}\', \'运维系统\' ), ( \'运维派单\', \'SMS_119076273\', \'您有新的(.+)工单无人[抢|接]单【工单号[::]([^】]+).+\', \'{"type":"","code":""}\', \'运维系统\' ), ( \'库存不足\', \'SMS_119091203\', \'.+【([^】]+)】.+库存已不足.+\', \'{"type":"","code":""}\', \'运维系统\' ), ( \'维修签到\', \'SMS_119076712\', \'.*您有(.*)未签到【工单号:([^】]+)】.+\', \'{"type":"","code":""}\', \'运维系统\' ), ( \'报警抢单\', \'SMS_119091869\', \'您有(.*)报警.*无人[抢|接]单【工单号[::]([^】]+).+\', \'{"type":"","code":""}\', \'运维系统\' ), ( \'广医派工\', \'SMS_135795374\', \'您有新的(.+)工单(.+)需处理,详情请打开“智慧机电运维系统APP”查看。\', \'{"type":"","code":""}\', \'运维系统\' ), ( \'报警签到\', \'SMS_119081998\', \'您有(.*)报警事件未现场签到【工单号[::]([^】]+).+\', \'{"type":"","code":""}\', \'运维系统\' ), ( \'未处理完崔单\', \'SMS_119076997\', \'您有(.*)处理尚未完成【工单号[::]([^】]+).+\', \'{"type":"","code":""}\', \'运维系统\' ), ( \'运维崔单\', \'SMS_119087014\', \'您有一条(.+)催单提示【工单号[::]([^】]+).+\', \'{"type":"","code":""}\', \'运维系统\' ), ( \'运维工单事件\', \'SMS_119091936\', \'您有新的工单事件【工单号[::]([^】]+).+\', \'{"type":"","code":""}\', \'运维系统\' ), ( \'MAN服务未找到异常\', \'SMS_120120306\', \'^【([^】]+)】异常(.+?)服务(【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*(服务【([^】]+)】未找到或者未安装!)*.+\', \'{"type":"","code":""}\', \'能管365\' )
JsonConvert.SerializeObject(v.Value.TemplateParam),把原来的对象进行序列化。
之前一直用的在线正则表达式匹配http://tool.oschina.net/regex/,不过发现不方便,于是我自己写了一个小工具。

源码下载:https://github.com/zouyujie/RegexTool
吐槽:阿里云的短信平台,短信模板中的单个变量长度不超过20个字符,而且还不支持组合变量,变量之间要用文字或者字符隔开,这样一来,假设我有需要发出去的变量文字是超过20个字符的,就不得不拆开,中间还要用字符或者汉字拆开,那么这样的话,客户收到的短信岂不是很奇葩,活生生的一些连续的描述文字被拆开了。
记录以备忘。