天天看点

正则表达式(入门)定锚点,去噪点,取数据

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

<code>.</code> 匹配不包括换行的任意字符,在php的s修饰符下面可以匹配换行,如<code>$pattern='#&lt;div&gt;(.*?)&lt;/div&gt;#s';</code>就可以匹配div内容有换行的数据。

<code>\s</code> 空格、tab

<code>*</code> 匹配零个或多个

<code>+</code> 匹配一个或多个,即至少一个

<code>\</code> 转义

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

<code>[]</code> 单字符取一个,比如[abc]会匹配<code>a或b或c</code>

但是,如果<code>[]</code>里面加上<code>^</code>则会变成排除这个字符,如<code>[^abc]</code>就表示<code>不是a、不是b、也不是c</code> 

另外,在<code>[]</code>里面可以使用<code>-</code>表示一个范围,如<code>[0-9]</code>表示从0到9,类似的还有<code>[a-zA-Z]</code>,如果要包含<code>-</code>字符,可以给它加上转义<code>[\-]</code>

<code>^</code> 一行字符串开始(虚拟字符,不实际存在)

这里的^跟<code>[]</code>里面用的<code>^</code>是同一个字符,但是却不是一个意思,这里它表示一行字符串的开始,比如<code>^www</code>表示以<code>www</code>开头的字符串,注意区分,不在<code>[]</code>里面的是开始符,在里面的排除

<code>$</code> 一行字符串结束(虚拟字符,不实际存在)

<code>{1,3}</code> 循环次数

<code>[0-9]{1,3}</code>表示在0-9的范围里面循环1个、2个或者3个,可能结果有5、20、415等

<code>?</code> 有两个用法

(1) 匹配一个或零个,比如<code>https?</code>匹配的<code>https</code>(一个s)或者http(零个s)

(2)非贪婪模式

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

<code>&lt;div&gt;</code>

<code>a</code>

<code>&lt;/div&gt;</code>

<code>b</code>

使用<code>&lt;div&gt;(.*?)&lt;/div&gt;</code>会得到2个结果:

因为,当遇到第一个<code>&lt;/div&gt;</code>,非贪婪模式就不会再往后找了。 

而使用<code>&lt;div&gt;(.*)&lt;/div&gt;</code>(贪婪模式)则会得到整个字符串

,因为它会匹配所有字符直到后面再找不到<code>&lt;/div&gt;</code>。 

11. <code>|</code> 多个数据选一(常用于多字符) 

前面提到<code>[]</code>里面的字符有选一个字符功能,但是假如不是一个字符,比如:http|ftp|svn 就需要用<code>|</code>分开,<code>|</code>的作用域是一直往后直到遇到括号,比如,对于源字符串

<code>http abc</code>

<code>ftp abc</code>

<code>svn abc</code>

<code>http|ftp|svn abc</code>匹配的结果是:

<code>http</code>

<code>ftp</code>

想要匹配 <code>http abc</code>和<code>ftp abc</code>和<code>svn abc</code>就要使用括号把前边的协议括起来,如<code>(http|ftp|svn) abc</code> 可以得到预期的结果。 

12. <code>()</code> 数据分界和取数据

上面例子<code>(http|ftp|svn) abc</code>就是数据分界的例子,然后,匹配结果会得到一个[1]的子集数据,这里就是子模式的概念,利用子模式,可以得到想要取出来的数据。子模式1、2、3的计算方法为左括号的计数,从左到右,从1开始,比如: 

<code>(http|ftp|svn)://([^/]+)</code>,[1]得到的是<code>(http|ftp|svn)</code>里面的数据,[2]得到<code>([^/]+)</code>里面的数据,对于嵌套括号也是点左括号即可。 

13. <code>(?:)</code> 非捕获组 

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

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

<code>&lt;div id="module_1"&gt;</code>

<code>&lt;div class="content"&gt;</code>

<code>content 1</code>

<code>&lt;div id="module_2"&gt;</code>

<code>content 2</code>

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

然后在对这个数据块的数据处理,得到class="contents"的内容即可。 

因此,这里用到2个正则:

(1)<code>&lt;div id="module_1"&gt;(.*?)&lt;/div&gt;\s*&lt;div id="module_2"&gt;</code> 

(2)<code>&lt;div class="content"&gt;(.*?)&lt;/div&gt;</code>

所谓去噪点,就是把无关的东西都当浮云,用通配符过掉它,只关心我们想要的数据,比如: 

<code>&lt;meta content="text/html; charset=utf-8" http-equiv="content-type"&gt;</code> 

要从这里得到字符集utf-8,我们需要怎么做? 

首先,定位锚点,有<code>&lt;meta</code> 、<code>charset=</code>和utf-8后面的<code>"</code>,其他都是浮云~ 

因此得到正则: 

<code>&lt;meta[^&gt;]*charset=([^"]+)"</code> 

即可,用子模式取数据[1]就能得到utf-8

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

本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/p/3807341.html,如需转载请自行联系原作者