这是我写的第一篇关于正则表达式的文章。至于正则表达式,在本科时代学习《编译原理》的时候,略微看过了一下,并没有深究。最近学习nutch的框架,当看到conf/regex-normalize.xml,完全傻眼了。为了进一步学习,不得不重新开始regex(正则表达式)。
一切从这里开始……
<!-- removes session ids from urls (such as jsessionid and PHPSESSID) -->
<regex>
<pattern>([;_]?((?i)l|j|bv_)?((?i)sid|phpsessid|sessionid)=.*?)(\?|&|#|$)</pattern>
<substitution>$4</substitution>
</regex>
要读懂这段代码,首先要搞懂regex中两个很重要的知识:
1、捕获分组
2、替换(substitution)
第一、捕获分组
基本概念:
regex中每个“()”(圆括号)之内的内容就是一个分组;第n(n=1、2、3……)个分组,可以用“$n”表示;每个分组的组号之间的大小关系是:右边的一定大于左边的,内层的一定大于外层的;换句话说,分组的序数=当前分组连同自己的左括号在内的左括号个数。
一些特殊情况:
1、"$0"表示整个符合
2、在java语言中,分组$n,若n大于分组总数的话,则会报错。
3、在java语言中,$23,只会被看做第23个分组。不会被看作第二个分组和普通字符“3”
举个例子说明一下吧:
regex:(a(b(b1))(c))(e)
RegexBuddy分析所得:(backreference,反向引用:即是指本文用的术语"分组")
Match the regular expression below and capture its match into backreference number 1 «(a(b(b1))(c))»
Match the regular expression below and capture its match into backreference number 2 «(b(b1))»
Match the regular expression below and capture its match into backreference number 3 «(b1)»
Match the regular expression below and capture its match into backreference number 4 «(c)»
Match the regular expression below and capture its match into backreference number 5 «(e)»
第二、替换(substitution)
提到替换,首先就要涉及三个关键词:
1、regex:描述需要抽取作进一步处理(替换)的子字符串(相对于整个输入的字符串)的特征
2、替换文本:描述替换效果(结果)的特征
3、源字符串:即输入的整个字符串
现在,一切回到原点(conf/regex-normalize.xml)吧……
结合强大的regexbuddy做个实验吧!
regex:([;_]?((?i)l|j|bv_)?((?i)sid|phpsessid|sessionid)=.*?)(\?|&|#|$)
替换文本:$1=I am kaiwingho;$3=I am Kaiwii
源字符串:www.kaiwii.com?Sid=who are u
输出结果:Sid=who are u=I am kaiwingho;Sid=I am Kaiwii
分析:
$1指代第一个捕获分组,即([;_]?((?i)l|j|bv_)?((?i)sid|phpsessid|sessionid)=.*?)。因为分组后面加上?,则表示这个分组所描述的内容可以出现1次或者0次,所以即使([;_]?((?i)l|j|bv_)?所描述的情况在源字符串压根没有出现,但是只要符合((?i)sid|phpsessid|sessionid)=.*?出现了就可以作为第一个分组所捕获的内容,即:Sid=who are u
【另外要说明一下的是,"(?i)"是一个regex元字符,表示它所在的分组的内容大小写忽略】
$3指代第三个捕获分组,即((?i)sid|phpsessid|sessionid),捕获内容:Sid(大小写忽略)
总结:
所以不难理解conf/regex-normalize.xml里面的意义:
从全部识别出来的内容保留$4,第四个捕获分组(即(\?|&|#|$)),因为里面描述的内容为Url中两个变量之间的连接符号,所以实现了目的:
<!-- removes session ids from urls (such as jsessionid and PHPSESSID) -->