分析一个复杂正则表达式
(?'Open'([\s]?)#item((-(?<itemName>.+?))?))(?<itemContentTpl>\s[\s\S]+?)(?'-Open'[\s]#item([\s]?))(?(Open)(?!))
一、表达式1:([\s]?)#item((-(?<itemName>.+?))?)
最开始的?'Open' 属于平衡组的知识,如果匹配到表达式1,则把Open压入栈中
([\s]?)表示匹配0或1次任何空白字符
(?<itemName>.+?) 匹配一个除“\n”和"\r"之外的任何单个字符一次或多次,并存入itemName组里
((-(?<itemName>.+?))?) 有-开头的0次或1次
二、表达式2:(?<itemContentTpl>\s[\s\S]+?)
\s[\s\S]+? 表示 匹配全部字符1次或多次,加了?表示惰性匹配,表达式2在表达式1和3之间,那就是取出表达式1和3之间的不可见字符开头后的所有字符
三、表达式3:(?'-Open'[\s]#item([\s]?))
?'-Open' 也属于平衡组的知识,如果匹配到表达式3,则把open弹出栈
四、表达式4:(?(Open)(?!))
如果栈中还有open,则无条件匹配失败,跟?'Open' 配合,表示有开头就必须有结尾,可以当作有左括号就必须有一个右括号匹配
五、总结
整个正则可以匹配位于两个#item之间的所有字符,把-之后的和\n\r之前的字符存进itemName组里,把两个#item之间的所有字符存进itemContentTpl组里
比如下面字符串,itemName组里的值是:“123” itemContentTpl组里的值是:"\r\n#{aa} #{bb} #{cc} #{dd}\r\n#{ee} \r"
而#{a} #{b} #{c} #{d}#{e} 没有匹配上,因为它并不是在两个#item之间
string str = @“#item-123 #{aa} #{bb} #{cc} #{dd} #{ee} #item #item #{a} #{b} #{c} #{d} #{e} ”;