专栏首页微光点亮星辰正则表达式学习笔记(初级篇)

正则表达式学习笔记(初级篇)

正则表达式学习笔记(初级篇)

序言

正则对于新人来说是一个头疼的名字,让人闻而生畏。但是,在我看来,正则,并没有那么神秘,希望能通过这篇正则表达式入门教程解除正则新人对于正则的畏惧感。

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

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

一、入门:正则字符

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

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

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

2. \s 空格、tab、换行

[\s\S]表示匹配任意字符,\S是\s的反义。

注意区分[\s\S]与.的区别。

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

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

5. \ 转义

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

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

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

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

关于[]常见的错误用法是:[ab|bc]用来表示ab或bc,实际上,它得到的结果是[abc|],即a或b或c或|这4个字符(单字符)的任意一个。这里可以改成(ab|bc)。

总结:[]里面的特殊符有五个:[]-\^,其他字符都是普通字符,包括*.?等。

说明:

* ^在[^的首位时候才有特殊意义

* [0-9 -在不是首尾的时候有特殊意义

* \[ \] 因为占用[]本身字符,所以有特殊意义

* \本身是转义符,有特殊意义

7. ^ 字符串开始

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

8. $ 字符串结束

9. {1,3} 循环次数

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

如果循环指定次数,如3次,则{3,3}可以简写成{3}。

如果刚好需要匹配字符{1},则正则需要给{进行转义,得到\{1}的正则。

如果{}中间不是数字,则{}本身不需要转义。

10. ? 有两个用法

(1) 匹配一个或零个

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

(2)非贪婪模式

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

<div>a</div><div>b</div>

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

<div>a</div>

<div>b</div>

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

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

<div>a</div><div>b</div>

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

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

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

1. http abc

2. ftp abc

3. svn abc

http|ftp|svnabc匹配的结果是:

1. http

1. ftp

1. svn abc

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

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

上面例子(http|ftp|svn) abc就是数据分界的例子,然后,匹配结果会得到一个[1]的子集数据(数组下标1),这里就是子模式的概念,子模式也叫分组,利用子模式,可以得到想要取出来的数据。子模式1、2、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分钟入门教程,这是我看过比较全面的正则入门资料。

二、操作:定锚点

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

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

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

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

1. <divid="module_1">
2.  <divclass="content">
3.               content 1
4.  </div>
5. </div>

然后在对这个数据块的数据处理,得到class="contents"的内容即可。 因此,这里用到2个正则:

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

当然,这个正则可以改进为: <div id="module_1">\s*<divclass="content">(.*?)</div>

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

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

三、操作:去噪点

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

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

四、操作:取数据

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

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

五、正则表达式高级教程

关于正则表达式的高级教程,请阅读《正则表达式学习笔记-高级篇》

本文分享自微信公众号 - 微光点亮星辰(SandTower),作者:大帝

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-03-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • springIOC源码分析

    学好spring 是有必要的 有人说spring就是javaee,javaee就是spring 。说对也对,说不对也不对。 当然本质肯定是不对了。 那为什...

    聚沙成塔
  • 数据库单表查询 - 简单筛选查询

    之前我们已经了解了SQL语言的分类,可以划分为:DDL(数据定义语言)、DML(数据操纵语言)、DQL(数据查询语言)、DCL(数据控制语言)、TPL(事务处...

    聚沙成塔
  • 大数据领域的正确打开方式

    大家好,非常荣幸能够和大家一同分享大数据领域相关的经验。首先简单的自我介绍一下,大家可以叫我小朱,之前从事JavaWeb开发,后来转为大数据开发,目前从事大数据...

    聚沙成塔
  • 基于光芯片的内存内计算(memory-in computing)

    这篇笔记介绍一篇牛津大学在光子计算领域的最新进展,该文章发表于最新一期的Science Advances,标题为“In-memory computing on ...

    光学小豆芽
  • HTML5 的拖放(实例:两个div之间拖放图片)

    首先,为了使元素(如本图片)可拖动,把 draggable 属性设置为 true :

    书童小二
  • Valgrind 使用入门

    Valgrind 是一套类似于 gprof 的动态检测的工具集,由于使用方便,不需修改目标程序源码,输出清晰图文并茂等优势,常被用作后台(特别是linux后台)...

    王纯
  • 金三银四铜五铁六

    ,以下全文均用LB代替)恰逢是这批面试大军其中的一名小兵,很不幸今年恰逢遇上了互联网寒冬(即各大公司都在裁员,对外提供岗位相对较少的,这意味着很多猿即将面临着更...

    lyb-geek
  • day2、Linux别名

    Linux中修改配置别名 ####用到的命令:   alias 是用来查看系统中有什么别名   source 让配置生效 临时取消别名的方法   unalias...

    863987322
  • HTML+CSS提升小实战

    1 <html> 2 <head> 3 <meta http-equiv="Content-Type" content="text/html; ch...

    别先生
  • yii2代码学习-BaseYii

    yii框架的v-2.0-alpha版本已经发布,PHP版本最低要求是PHP-5.4,将会在今年早些时候推出正式版。阅读yii2的代码,能学到很多东西,代码写的很...

    luxixing

扫码关注云+社区

领取腾讯云代金券