前两天做搜狗的笔试题,有一道是关于正则表达式的题目:提取出一个HTML文件里的所有超链,顿时束手无策了
关于正则表达式只知道一些ABC,对于较高级的应用还不是很清楚,于是去借阅了《正则表达式必知必会》,很不错的快速上手书籍。
这里记录的只是一些自己的ABC之外的东西,最基础的一些是木有地^_^
1、字符集的取非匹配
[^1-9],即采用元字符^
2、匹配空白字符
[\b] 回退并删除一个字符 \f 换页符
\n 换行符 \r 回车符
\t 制表符 \v 垂直制表符
\r\n是Windows系统所使用的文本行结束标签,在Unix系统下采用\n
3、匹配特定的元字符
\d 等价于[0-9] \D 等价于[^0-9]
\w [a-zA-Z0-9] \W [^a-zA-Z0-9]
\s [\f\v\r\t\v] \S [^\f\v\r\t\n]
另外使用\x来匹配十六进制数值,使用\0来匹配8进制数值
4、重复匹配指定匹配的次数
精确次数:{6} 次数区间{2,4} 至少匹配多少次:{2,}
防止过度匹配的元字符(懒惰性元字符):
*? +? {n,}?
5、位置匹配
单词边界: \b来表示一个单词的开始或结尾
它是这样一个位置:这个位置位于一个能够用来组成单词的字符(\w)和一个不能用来组成单词的字符(\W)之间
\B用来匹配一个非单词边界
字符串边界:
^ 匹配字符串开头
$ 匹配字符串结尾
通常是将需要匹配的整个文本作为一个字符串的,因此有了字符串边界的分行匹配模式:
(?m)
此元字符必须出现在整个模式的最前面
6、与正常的逻辑运算符相同,| 的优先级是较低的,比如19|20\d{2}将匹配19或者以20开头的四位数
7、回溯引用
回溯引用解决的是匹配模式中已经出现的字串问题,比如重复单词、html文件里的标签匹配等
[ ]+(\w+)[ ]+\1 此模式匹配重复出现的单词,\1代表前面子表达式(\w+)所匹配的内容
<[hH]([1-6])>.*?<[hH]\1> 匹配html文件中出现的成对标题标签
回溯引用经常使用的场合是在复杂场合中的替换操作:
替换操作需要使用到两个正则表达式,一个搜索模式,另一个用来给出匹配文本的替换模式,回溯引用可以跨模式使用,下面的例子用来将一个电子邮件地址替换问超级链接:
正则表达式:(\w+[\w\.]*@[\w\.]*\.\w+)
替换:<A HREF=”mailto:$1”>$1</A>
另一个例子:将0951-5038528这种电话号码替换为(0951)5038528:
正则表达式:(\d{4})(-)(\d{7})
替换:($1)$3
8、前后查找
前后查找解决的是查找以某模式开头(或结尾)的串,但是又不想匹配该开头(结尾)模式,比如匹配一个html文件中的所有超级链接。
向前查找:一个向前查找模式其实就是一个以?=开头的子表达式,需要匹配的文本在=后面,如匹配一个url地址中的协议字段:.+(?=:),即在该模式中=后面的模式不需要返回(不消费)。
向后查找:向后查找的操作符是?<=,同样=后跟要匹配的文本,但是不消费。如模式:(?<=$)[0-9.]+匹配一个商品的价格,但是并不返回$符号
至此,一个匹配html文件中的所有超链的正则表达式就可以写出来了:
(?<=([Hh][Rr][Ee][Ff]=")).*?(?=")即以href="开头,以"结尾的串,并且对中间的部分进行懒惰匹配。
对前后查找取非:
(?!) 负向前查找
(?<!) 负向后查找
9、嵌入条件匹配-回溯引用匹配
正则表达式里面的条件用?来定义
两个具体的例子:
(1) 匹配一段文本里的所有<IMG>标签,如果这个标签是一个链接,需要找出正处整个链接标签:
(<[Aa]\s+[^>]+>\s*)?<[Ii][Ma][Gg]\s+[^>]+>(?(1)\s*[Aa]>)
解释:(<[Aa]\s+[^>]+>\s*)?匹配一个<A>标签及其属性,这个标签可有可无,然后接着匹配一个<IMG>标签及其属性,最后的括号里是一个回溯应用条件:如果第一个回溯引用匹配到(存在),则使用后面的模式继续进行匹配
(2) 下面的例子提供了一个否则解决的方案,即如果回溯引用匹配到了下面怎样匹配,如果匹配不到应该按什么来匹配。该方案匹配一个电话号码,该号码应该是如下形式:
123-456-7890 或者(123)456-7890
正则表达式:(\()\d{3}(?(1)\)|-)\d{3}-\d{4}
解释:如果匹配到左括号,则在3个数字之后匹配右括号,否则,匹配连字符
10、嵌入条件匹配-前后查找条件
前后查找条件只是在一个向前匹配或向后匹配成功后才允许一个表达式被使用,只需要将括号中的回溯引用编号替换为一个完整的前后查找表达式即可。
一个例子:匹配美国的邮政编码,有两种形式:xxxxx或xxxxx-xxxx
正则表达式:\d{5}(?(?=-)-\d{4})