一个自定义表达式的正则表达式解析


最近做了一个关于导入Excel数据的简单工具,设计思路如下: 

  1.使用XML描述配置关系

  2.引入简单表达式/函数对数据进行转换,处理

  3.支持灵活的扩展功能.


对EXCEL的转换配置定义如下:

<transform id="ts1" source="s1" target="t1">

<columns>

<column name="ID" dataType="int" type="autoint"/>

<column name="SITECODE" source="#Replace([$.2,$.1,$.3],[c1],[SiteName,RiverName],[SiteCode])" dataType="String"/>

<column name="SITECODE2" source="#Replace([$.2,c1,SiteCode)" dataType="String"/>

<column name="SITENAME" source="$.断面名称" dataType="String"/>

<column name="SAMPLINGTIME" source="#DateTime([$.采样日期],[yyyy-MM-01])" dataType="String"/>

<column name="SAMPLINGTIME2" source="#DateTime($.采样日期,yyyy-MM-01)" dataType="String"/>

<column name="SAMPLINGTIMESTR" source="#Date($.采样日期,[yyyy年MM月dd日])" dataType="String"/>

<column name="W_TEMP" source="$.4"/>

<column name="PH" source="$.5"/>

<column name="DO1" source="$.6"/>

<column name="CODcr" source="$.7"/>

<column name="NH4_N" source="$.8"/>

<column name="CODMN" source="$.9"/>

<column name="WaterGrade" source="#REPLACE([$.10],[c2],[name],[code])"/>

<column name="WaterGrade2" source="#REPLACE($.10,c2,name,code)"/>

<column name="WaterQuality" source="$.10"/>

<column name="TBR" source="#GET([s4,s5],[0],[1])"/>

<column name="SHR" source="#GET([s4,[3])"/>

<column name="YWZGFZR" source="#GET([s4,[6])"/>

<column name="TBRQ1" source="#SUBSTRING([#GET([s4,[3,4],5)],[5])"/>

<column name="TBRQ2" source="#SUBSTRING(#GET([s4,3,5),5)"/>

<column name="TBRQ3" source="#SUBSTRING(#GET([s4,[1-3],simsun;color:#002060;"> <column name="TBRQ" source="#DATETIME(#.TBRQ3,yyyy-MM-dd)"/>

<column name="REMARK" source="IMPORT"/>

<column name="ADDTIME" source="%NOW%"/>

<column name="UPDATETIME" source="%NOW%"/>

</columns>

</transform>

其中,source中的各种#,$,还有%等的字符串,为自定义的处理函数/表达式/常量,为了简单,现阶段函数表达式调用,只支持嵌套一层,上面代码中的(#SUBSTRING(#GET...)

定义的优先级规则为: 函数->表达式->常量


source的内容解析, 起初使用基于字符串匹配的方式, 勉强凑合工作, 但是马上就遇到了问题:


  源:   #Replace([$.2,[SiteCode])


解析目标: ReplaceFunctionExpression

Arguments[0]-> ExpressionCollection[3]->DataItemExpression

Arguments[1]-> c1 : StringExpression

Arguments[2]-> ExpressionCollection[2]->StringExpression

Arguments[3]-> SiteCode : StringExpression


  如上:函数的参数之间是用逗号隔开的,但是参数有可能是另一个表达式,或者一个数组[,],这样子,使用切分字符串的方式来解析函数的参数(尤其是参数为其他函数/表达式)就有问题了


记得数据结构中有中缀表达式和后缀表达式解析的算法,应该是可以实现本例的要求,但是时间有限,也不需要一个很强大的功能,所以还是没有采用,最后的解决方案,还是采用正则表达式来解析.


最终构造的正则表达式为:


@"\[?\#(?<fn>\w+)\((?<fp>(.*?)+)\)\]?|\[(?<fp2>([-\$\.\#%\w]+,)*[-\$\.\#%\w]+)\]|\[?(?<fp3>[-\$\.\#%\w]+)\]?"


测试的样例字符串:


//#GET([s4,[5],[#GET2([s6,s7],8,9)],[100],110,[$.1,s31,s41,s51,你好],weixq,[$.中国,$H.5,#.99],$.22,#DateTime([$.采样日期],[yyyy-MM-01]),[yyyy-MM-01]


输出的匹配结果:


Result:12

1.Success:[True],Index:[0],Length:[17],Value:[#GET([s4,5)].

2.Success:[True],Index:[18],Length:[3],Value:[[5]].

3.Success:[True],Index:[22],Length:[20],Value:[[#GET2([s6,9)]].

4.Success:[True],Index:[43],Length:[5],Value:[[100]].

5.Success:[True],Index:[49],Value:[110].

6.Success:[True],Index:[53],Value:[[$.1,你好]].

7.Success:[True],Index:[74],Value:[weixq].

8.Success:[True],Index:[80],Length:[16],Value:[[$.中国,#.99]].

9.Success:[True],Index:[97],Length:[4],Value:[$.22].

10.Success:[True],Index:[102],Length:[33],Value:[#DateTime([$.采样日期],[yyyy-MM-01])].

11.Success:[True],Index:[137],Length:[12],Value:[[yyyy-MM-01]].

12.Success:[True],Index:[150],Value:[[ND,%ND,%ND%,ND%]].


其中解析的结果做为下一轮函数/表达式的输入,继续解析,直到不能在分解.


希望能给解析自定义字符串的朋友们一点启发:)

相关文章

jquery.validate使用攻略(表单校验) 目录 jquery.validate...
/\s+/g和/\s/g的区别 正则表达式/\s+/g...
自整理几个jquery.Validate验证正则: 1. 只能输入数字和字母...
this.optional(element)的用法 this.optional(element)是jqu...
jQuery.validate 表单动态验证 实际上jQuery.validate提供了...
自定义验证之这能输入数字(包括小数 负数 ) &lt;script ...