正则(转)

正则对于新人来讲是一个头疼的名字,让人闻而生畏。可是,在我看来,正则,并无那么神秘,但愿能经过这篇正则表达式入门教程解除正则新人对于正则的畏惧感。javascript

接触正则应该有三年不止了吧,我也不知道本身怎么就走过了畏惧正则的时期,并且在一个小圈子里面还成了正则强人。php

今天就基于我对正则的理解,简单描述一下我眼里的正则,但愿这篇正则表达式入门教程可以解除正则新人对于正则的畏惧感。html

 

 

先归纳一下,正则三段论:java

 

定锚点,去噪点,取数据

 

1、入门:正则字符

关于正则字符,不少文章都会讲到,足足有一篇文章才能描述清楚,我这里就很少说,对于我,平时,经常使用的有:正则表达式

 

1. . 匹配不包括换行的任意字符

在php的s修饰符(单行模式)下面能够匹配换行,如$pattern='#<div>(.*?)</div>#s';就能够匹配div内容有换行的数据。vim

若是须要匹配包括换行的任意字符,可使用[\s\S]代替.数组

 

2. \s 空格、tab、换行

[\s\S]表示匹配任意字符,\S是\s的反义。
注意区分[\s\S]与.的区别。
 

3. * 匹配零个或更多个,即0~n

 

4. + 匹配一个或更多个,即至少一个,1~n

 

5. \ 转义

一个特殊字符前加\就表示转义,说明把它当普通字符用ide

 

6. [] 单字符取一个,好比[abc]会匹配a或b或c

可是,若是[]里面加上^则会变成排除这个字符,如[^abc]就表示不是a、不是b、也不是c 
另外,在[]里面可使用-表示一个范围,如[0-9]表示从0到9,相似的还有[a-zA-Z],若是要包含-字符,能够给它加上转义[\-]。 
关于[]常见的错误用法是:[ab|bc]用来表示abbc,实际上,它获得的结果是[abc|],即a或b或c或|这4个字符(单字符)的任意一个。这里能够改为(ab|bc)。 
总结:[]里面的特殊符有五个:[]-\^,其余字符都是普通字符,包括*.?等。 
说明: 
^[^ 的首位时候才有特殊意义 
[0-9 -在不是首尾的时候有特殊意义 
\[ \] 由于占用[] 自己字符,因此有特殊意义 
\自己是转义符,有特殊意义svn

 

7. ^ 字符串开始

这里的^跟[]里面用的^是同一个字符,可是却不是一个意思,这里它表示整个字符串的开始,好比^www表示以www开头的字符串,注意区分,不在[]里面的是开始符,在里面的排除学习

 

8. $ 字符串结束

 

9. {1,3} 循环次数

[0-9]{1,3}表示在0-9的范围里面循环1个、2个或者3个,可能结果有五、20、415等。 
若是循环指定次数,如3次,则{3,3}能够简写成{3}。 
若是恰好须要匹配字符{1},则正则须要给{进行转义,获得\{1}的正则。 
若是{}中间不是数字,则{}自己不须要转义。

 

10. ? 有两个用法

 

(1) 匹配一个或零个

好比https?匹配的https(一个s)或者http(零个s)

 

(2)非贪婪模式

所谓非贪婪模式,就是匹配尽量少的内容,好比,对于源字符串

 
  1. <div>a</div><div>b</div>

使用<div>(.*?)</div>会获得2个结果(注意:若是源字符串有换行,使用[\s\S]替换 . ):

 
  1. <div>a</div>

 
  1. <div>b</div>

由于,当遇到第一个</div>,非贪婪模式就不会再日后找了。 
而使用<div>(.*)</div>(贪婪模式)则会获得整个字符串

 
  1. <div>a</div><div>b</div>

,由于它会匹配全部字符直到后面再找不到</div>

更多关于?的使用,能够参考《正则表达式匹配次数

 

11. | 多个数据选一(经常使用于多字符)

前面提到[]里面的字符有选一个字符功能,可是假如不是一个字符,好比:http|ftp|svn 就须要用|分开,|的做用域是一直日后直到遇到括号,好比,对于源字符串

 
  1. http abc
  2. ftp abc
  3. svn abc

http|ftp|svn abc匹配的结果是:

 
  1. http

 
  1. ftp

 
  1. svn abc

想要匹配 http abcftp abcsvn abc就要使用括号把前边的协议括起来,如(http|ftp|svn) abc 能够获得预期的结果。

 

12. () 数据分界和取数据

上面例子(http|ftp|svn) abc就是数据分界的例子,而后,匹配结果会获得一个[1]的子集数据(数组下标1),这里就是子模式的概念,子模式也叫分组,利用子模式,能够获得想要取出来的数据。子模式一、二、3的计算方法为左括号的计数,从左到右,从1开始,好比: 
(http|ftp|svn)://([^/]+),分组1获得的是(http|ftp|svn)里面的数据,分组2获得([^/]+)里面的数据,对于嵌套括号也是点左括号便可。在正则中有不少与括号结合的写法,你在数左括号的时候,必定要注意,非捕获组和环视的左括号都是不须要数的。 
在使用子模式过程当中,常见两种写法是:\1 和 $1。 
(1) \1 是在正则表达式自己中引用分组1的内容,如: 
咱们要匹配111这样的连续出现3此的数字,咱们能够写出正则:(\d)\1\1(\d)匹配到第一个1,后面再引用这个匹配内容,获得111。 
(2) $1 是在替换中调用分组的内容,如: 
咱们要替换连接参数name=Zjmainstayusername=Zjmainstay,咱们可使用正则name=([^&]+)替换为username=$1来实现,这里的$1就引用了分组1的结果Zjmainstay,所以获得咱们想要的结果。

 

13. (?:) 非捕获组

上面说到()做为子模式能够获得它里面的数据,可是,有些时候,()只是做为数据分界功能,并不须要取出来,这时候就要用到非捕获组的概念了。好比:(http|ftp|svn)://([^/]+)只想获得域名,也就是[2],那么(http|ftp|svn)就只是数据分界的功能,这里不须要捕获,所以使用非捕获组功能,(?:http|ftp|svn)屏蔽这部分的数据获取,此时,(?:这个左括号排除[1]计数,也就是(?:http|ftp|svn)://([^/]+)中的([^/]+)变成[1]了。

 

14. 分隔符

在一些语言中,你会发现正则第一个和最后一个字符是相同的,如: 
/\d+/ 
这个/ /在PHP中称为分隔符,正则表达式须要由分隔符闭合包裹。在PHP中,分隔符可使任意非字母数字、非反斜线、非空白字符。这个概念很关键,它能帮助咱们简化一些正则的书写,避免错误,如: 
/<div>.*?</div>/ 
这个正则是错误的。 
缘由是</div>/与分隔符相同,可是却没有作转义。 
以下程序:

 
  1. preg_match('/<div>.*?</div>/', '<div>abc</div>', $match);

PHP中会收到错误提示:Warning: preg_match(): Unknown modifier 'd' in regexTest.php on line 2 
对于这种状况,有两种解决方案: 
(1)/<div>.*?<\/div>/ 
(2)#<div>.*?</div># 
方案(1)是对正则内部的分隔符作转义,方案(2)是规避了原本的/分隔符,使用#做为分隔符,从而避免/须要转义。 
虽然不少状况下,都是看到先后一致的分隔符,可是,你们须要了解一下,[<div>.*?</div>]这个表达式在PHP里也是合法的。(不提倡使用,仅了解!)

 

15. 模式修饰符

模式修饰符在许多程序语言中都支持的,好比最多见的是i,不区分大小写,如javascript里的/[a-z0-9]/i,表示匹配字母数字,不区分大小写。

本人在写php正则时经常使用的模式修饰符主要有is,如: 
$pattern = '#[a-z0-9]+#is';

模式修饰符s的做用主要是的.可以匹配换行,在处理换行数据时,一般会用到。

在PHP中,模式修饰符有两种用法,一种是上面的,在分隔符后面的模式修饰符,它的做用范围是全局;另外一种是在正则表达式中间的。 
例如:

 
  1. 正则:/((?i)[A-Z]+)c/
  2. 测试字符:abcABC
  3. 匹配:abc
  4. 说明:局部(ab)的大小写被忽略了,(?i)的做用范围在分组1

若是把正则改为:/([A-Z]+)c/i,则匹配结果将是:abcABC 
示例地址:PHP正则表达式中间的模式修饰符 (选择Version 1/2切换版本查看结果区别)

关于PHP模式修饰符的讲解,请查看PHP手册中的《PHP模式修饰符》。


关于经常使用字符的使用差很少到这里,还有更多的请参考正则表达式30分钟入门教程,这是我看过比较全面的正则入门资料。

 

2、 操做:定锚点

注:这里的锚点区分于正则本来关于锚点的定义,此处是肯定的参照文本的意思,如a标签里的<a

每个正则都是有针对性的,只有这样正则才有意义。所以,写正则以前,先观察你要解析的数据,找准惟一的锚点,好比,你要解析一个页面的title标签,获得title内容,那么这个title就是锚点。有时候,所要取的数据确实没法定位一个惟一的锚点,那么,你能够分解数据,先经过一个惟一锚点锁定你的数据块,取出来以后,再对这个数据块取数据便可。好比,有这么一段源字符串:

 
  1. <div id="module_1">
  2. <div class="content">
  3. content 1
  4. </div>
  5. </div>
  6. <div id="module_2">
  7. <div class="content">
  8. content 2
  9. </div>
  10. </div>

你直接经过class="content"来匹配数据的话很明显会获得两个,那么,你能够扩展它的数据域,先以id="module_1"做为锚点,获取整个

 
  1. <div id="module_1">
  2. <div class="content">
  3. content 1
  4. </div>
  5. </div>

而后在对这个数据块的数据处理,获得class="contents"的内容便可。 
所以,这里用到2个正则:

(1)<div id="module_1">(.*?)</div>\s*<div id="module_2"> 
(2)<div class="content">(.*?)</div>

固然,这个正则能够改进为: 
<div id="module_1">\s*<div class="content">(.*?)</div>

注:为了更清晰查看,前面源码作了换行,匹配失败的朋友,能够修改 .*? 为 [\s\S]*? 修正正则。

 

总结:锚点,就是能惟必定位你数据的标识

 

3、 操做:去噪点

所谓去噪点,就是把无关的东西都当浮云,用通配符过掉它,只关心咱们想要的数据,好比: 
<meta content="text/html; charset=utf-8" http-equiv="content-type"> 
要从这里获得字符集utf-8,咱们须要怎么作? 
首先,定位锚点,有<meta 、charset=和utf-8后面的",其余都是浮云~ 
所以获得正则: 
<meta[^>]*?charset=([^"]+)" 
便可,用子模式取数据[1]就能获得utf-8

 

总结:关心的留下,不关心的都是浮云

 

4、 操做:取数据

关于取数据,上面一大篇下来你们应该有概念了,就是利用子模式来获取,这里再也不赘述。

 

总结:子模式计数,数左括号从1开始,排除非捕获组的左括号

 

5、正则表达式高级教程

关于正则表达式的高级教程,请阅读《深刻正则表达式应用 - 正则表达式高级教程

 

最后,但愿你们有一个愉悦的正则之旅,你必定会爱上她的,跟我同样。: )

转载请附带本文原文地址: 我眼里的正则表达式入门教程,首发自  Zjmainstay学习笔记
相关文章
相关标签/搜索