最近做一些东西经常用到正则表达式,而且经常改动。如果把正则写成常量,需要转义,看起来很坑爹。如果配置到xml,一个麻烦,另外xml特殊字符也需要转义,仍然坑爹。为了能让正则表达式可配置,看起来又好维护,我将正则表达式放到一个txt里面,每行一个,格式为{name}##{regex},同时支持#开头的注释。下面是加载解析代码:
/// <summary>
/// 正则表达式加载类
/// </summary>
internal static class RegExps
{
static RegExps()
{
string line = "";
int lineNum = 1;
string file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"Config\\reg.txt");
const string ERROR_FORMAT = "{0}。格式应为{name}##{value}, line {1} of file {2} 。";
if (!File.Exists(file))
throw new ArgumentException(String.Format("文件 '{0}' 不存在", file));
using (StreamReader reader = new StreamReader(file))
{
_RegDic = new Dictionary<string, Regex>();
while ((line = reader.ReadLine()) != null)
{
if (String.IsNullOrWhiteSpace(line) || line.StartsWith("#"))
continue;//跳过空行和注释
else
{
int splitPos = line.IndexOf("##");
if (splitPos == -1)
throw new ArgumentException(String.Format(ERROR_FORMAT, "缺乏##分隔符", lineNum, file));
string key = line.Substring(0, splitPos).Trim();
string regex = line.Substring(splitPos + 2).Trim();
if (key == String.Empty)
throw new ArgumentNullException(String.Format(ERROR_FORMAT, "缺乏表达式名称", lineNum, file));
if (regex == String.Empty)
throw new ArgumentNullException(String.Format(ERROR_FORMAT, "缺乏值", lineNum, file));
try
{
Regex reg = new Regex(regex, RegexOptions.Compiled);
_RegDic[key] = reg;
}
catch (ArgumentException exp)
{
throw new ArgumentException(String.Format(ERROR_FORMAT, "正则表达式格式错误:" + exp.Message, lineNum, file));
}
}
++lineNum;
}
}
}
public static Regex GetReg(string name)
{
if (_RegDic.ContainsKey(name))
return _RegDic[name];
else
{
throw new ArgumentException(String.Format("The regex {0} doest not exist, please check reg file.", name),
name);
}
}
private static Dictionary<string, Regex> _RegDic = new Dictionary<string, Regex>();
}
下面是个正则配置文件例子,reg.txt:
#例子1
reg1##(?si)<div>.*</div>
#例子2
reg2##(?si)<a>.*</a>
使用的时候直接
var reg RegExps.GetReg("reg1");
//使用reg的代码
注意:reg.txt文本必须保存成utf-8,否则中文可能乱码,不过影响也不大,因为注释一般采用中文,不过要是正则名称是中文就必须保证编码了。