正则表达式学习笔记

正则表达式学习笔记

(原创内容,转载请注明来源,谢谢)

首先,学习正则表达式,很推荐一篇博客,http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html,deerchao写的《正则表达式30分钟入门教程》,看完他的文章,基本上可以在实际中使用正则表达式,本文是结合此博客和一些其他书籍的内容的学习笔记。

一、基础内容

我认为的基础内容包括以下7点,掌握后可以使用正则匹配很多内容。

1、位置

正则表达式表示位置的字符有^(表示字符串开始)、$(字符串结束)、\b(字符串开始或结束)。

在明确需要匹配的位置的情况下,建议使用^、$,因为其会加快字符串的匹配速度。

2、数量

正则表达式表示数量的主要有*(匹配任意次)、?(匹配0次或1次)、+(匹配1次或多次)、[](中括号内的内容匹配其中一个一次)、{m,n}(匹配m至n次,n省略则匹大于或等于m次,逗号也省略则匹配m次)。

3、字符组

字符组为使用一些特殊的方式表示一组同样规律的内容。\d表示0-9任意一个数字,

\s表示任意个空白字符(空格),\w表示任意大小写字母、数字、下划线、中文。.(点)表示换行符以外的任意内容。

字符组和数量常常组合起来使用,如匹配四位数字可以用\d{4}。

4、反义

^符号用在正则的第一个位置表示字符串的开始,但是用在[]内部则表示非,例如[^\d]表示匹配1个不是数字的字符。其他还有\W(表示非\w)、\D(表示非\d)、\S(表示\s)、[^abc]表示匹配abc以外的字符。

5、转义

转义使用反斜杠\,这个和很多程序语言相同。即\\匹配\,\.匹配.等。

6、分支

分支符号为|,和程序语言中的||意思相似,表示或的意思。例如要匹配my和mine,可以使用m(y|ine)进行匹配。

7、分组

分组采用()(小括号)把内容放在里面,通常分组后可以加上表示数量的词,进行批量匹配。例如要匹配的内容是三个数字加一个字母a,一共匹配10次,可以用(\d{3}a){10}。

二、进阶内容

除了上述内容,正则表达式提供了一些高级的功能,让匹配更加全面与方便。

1、捕获

1) (?<name>exp),该含义为匹配表达式exp,并将其命名为name,后面的匹配中可以用\k<name>表示匹配到的内容。

例如,(?<myname>\d{4})\w?\k<myname>,表示把第一次匹配到的4个数字存在myname内,后面就用\k<mynname>再次匹配即可。

2) 捕获还有其他写法,如(exp),表示不给exp取名字,该情况下会保存在系统默认名字内,从1开始编号。例如(\d)\w(\d{5})\w\1\w\2,表示第一次捕获的一个数字存在\1内,第二次捕获的五个数字存在\2内。

3) 因此,在正则表达式中,括号应当慎用,因为每个括号正则都会将其捕获,并进行存储,如果在长字符串匹配的情况下,又使用了大量的括号,将占用较多存储空间。另外,如果不需要捕获内容,可以使用(?:exp),表示不捕获文本,也不进行编号。

2、零宽断言

零宽断言也是类似$、^等表示位置的字符,但是对该位置上的字符有一定的要求。主要有四个表达方式。

1) (?=exp),表示该位置的内容要满足exp的要求时,匹配exp之前的内容。例如\w+(?=ing),会匹配doing的do。

2) (?<=exp),表示该位置的内容要满足exp的要求时,匹配exp之后的内容。例如\w+(?<=re),会匹配reading的ading。

3) (?!exp),表示该位置的内容不是exp时,匹配exp之前的内容。例如\b\w+(?!ing)\b,会匹配不含ing结尾的任意单词。

4) (?<!exp),表示该位置的内容不是exp时,匹配exp之后的内容。例如\b\w+(?!re)\b会匹配任意不是以re开头的单词。

上述内容中,3)、4)又称为负向零宽断言。

3、注释

(?#comment)表示注释,不会被解析,仅仅是便于其他人员查看正则表达式。

4、懒惰匹配

1) 懒惰匹配表示匹配尽量少的内容,在匹配符后面加上一个?即可。*?表示重复任意次,但是尽可能的少重复;{10,}表示重复10次以上,但是尽可能少重复。其他数量词加上?也一样,表示满足基本条件的情况下尽可能少匹配。

例如,a.*?b在字符串abaab中会匹配到ab。

2) 与懒惰匹配相对应的,就是贪婪匹配,在不加?情况下,前面说的内容都是贪婪匹配。

3) 为了使程序匹配速度更快,在确定只需要懒惰匹配的情况下,需要加上?,可以最快匹配到需要的内容。

5、优先级问题

优先级从高到低,依次是:

1) \

2) ()、(?=)、(?=)、[]

3) *、+、?、{n}、{n,}、{n,m}

4) ^、$、任意字符

5) |

三、PHP正则表达式匹配函数

1、preg_math

官方文档int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )

常用到前三个参数,$pattern表示匹配的模式,$subject表示需要匹配的字符串,如果提供了参数matches,它将被填充为搜索结果。$matches[0]将包含完整模式匹配到的文本,$matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。

函数返回:pattern 的匹配次数。它的值将是0次(不匹配)或1次,因为preg_match()在第一次匹配后 将会停止搜索。

2、preg_match_all

官方文档int preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags = PREG_PATTERN_ORDER [, int$offset = 0 ]]] )

前三个参数和preg_math一样,返回完整匹配次数(可能是0),或者如果发生错误返回FALSE。该函数匹配成功一次后,会从匹配成功的最后一个位置开始,继续往后匹配。

3、常用模式

preg_math和preg_math_all的$pattern,需要输入的字符串都是 ‘%exp%’,即在正则表达式的基础上,前后加上两个%。通常来说,不使用%,而用其他符号也可以,只需要保证前后一致即可。实际工程中,为了项目统一,最好定一个一致的号码。

1) 忽略大小写

$pattern = ‘%exp%i’,即在第二个%后面加一个字母i即忽略大小写匹配。

2) 点号通配模式

点号通配模式表示元字符.(点)忽略换行。使用方法是$pattern= ‘%exp%s’

3) 多行模式

多行模式表示,当$pattern是多行内容时,如果加上$、^,该模式下,会将$、^之间的内容当成一行内容,忽略字符串当中的换行\n。使用方法是$pattern = ‘%exp%m’

4) 懒惰模式

类似于正则表达式的懒惰模式,使用方法是$pattern = ‘%exp%U’

5) 结尾限制模式

该模式下,结尾不能有换行,否则匹配失败。使用方法是$pattern = ‘%exp%D’

6) 支持UTF-8转义表达方式

如果汉字等被用UTF-8编码,则需要开启此模式进行匹配。使用方法是$pattern = ‘%exp%u’

四、实际应用

1、校验

如手机号校验,要判断手机号是否为移动的号码,即要确定开头为135-139、150-151、157-159、182、183、188的手机号,表达式如下:

(?:13[4-9]|15[01789]|18[238])\d{8}

2、数据安全

当给用户提供输入框时,用户可能往里面输入js代码对网站进行破坏,这个称为XSS攻击,因此可以用正则表达式把所有的<>或者</>去掉。表达式如下:

<\/?[^>]+>

3、URL重定向

在Apache和Nginx中,经常需要配置url的rewrite,可以把php后缀的文件重定向到html后缀的文件中,这样做便于搜索引擎的检索。

假设需要把test.php?name=a&page=1重定向为test_a_1.html,在apache的.htaccess中,可以如下方式:

RewriteEngine on

RewriteRule index.html index.php

RewriteRule test_([a-z]+)(\d?)\.htmltest.php?name=$1&page=$2[NC]

NC表示忽略大小写,rewriteengineon是开启rewrite的意思。

五、PHP正则表达式的优化

当字符串很长,需要匹配的模式串也很长的时候,需要尽可能的对正则表达式进行优化,否则会降低程序运行速度。

1、满足匹配前提下少用|

|符号效率较低,需要逐个进行匹配,例如[abc]和[a|b|c],|会把内容分别进行匹配。

2、限定量词优先

在确定需要匹配次数的情况下,尽量不要使用*、+、{n,}等不限定长度的量词,否则会进行多次的查找。

3、优先用preg_match/命中率最高的匹配项放最左侧

因为其匹配到就停止,而preg_match_all会把全部内容匹配完。同样,在多个匹配条件情况下,把最有可能命中的情况放在最左侧,则匹配到就不会继续往后匹配。

4、合理使用括号

括号会占用存储空间,大量匹配的情况下慎用。

5、使用PHP自带的一些函数

1) 当可以确定需要的字符串的位置时,尽量使用字符串匹配函数,即str开头的函数,匹配速度更快。

2) 需要匹配PHP的源码,可以安装使用PHP自带的Tokenizer分析函数,可以准确的分析PHP的变量、常量、类名、方法名等。

3) 解析URL时,可以用PHP自带的parse_url()函数,该函数可以把url的类型、host、path、query等输出。

4) 获取HTTP头,可以使用PHP自带的get_headers()函数,该函数可以捕获到HTTP头的信息,并用数组方式返回。

5) 验证邮箱信息、URL信息、数据类型等,均可以安装使用PHP的filter_var函数,该函数可以使用特定的过滤器过滤一个变量。

六、验证正则表达式的正确性

网上有很多验证工具,我个人比较喜欢的是http://tool.lu/regex/

——written by linhxx 2017.07.05

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-07-05

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏我的博客

PHP中处理html相关函数集锦

1、html_entity_decode() 函数把 HTML 实体转换为字符。 Html_entity_decode() 是 htmlentities() ...

2676
来自专栏柠檬先生

Angularjs基础(十一)

ng-csp       描述:修改内容的安全策略       实例: 修改AngularJS 中关于"eval"的行为方式及内联样式;         ...

2185
来自专栏农夫安全

注入学习之sqli-labs-5(第四次)

前言 第七关先跳过,先把get注入系列讲完再来讲 不知道大家有没有玩过一个猜数字的游戏 我给出一个数的范围,比如1-100,然后你去猜,我只会回答你对或者错。 ...

34310
来自专栏学习有记

XML进阶:Level 1 - XML简介

1133
来自专栏python全栈布道师

关于python装饰器可能是最全的一篇文章(包括有用的例子)

一个常见错误是使用装饰器时不保存函数元数据(文档字符串和函数名字), 装饰器返回的是新函数,失去了函数元数据.

692
来自专栏精讲JAVA

OutOfMemoryError异常系列之方法区溢出

继续上一篇文章讲解,在上一篇中给大家留下了一个小问题,就是在jdk1.6中返回的是两个false,在jdk1.7中返回的是true false,,上一次代码没有...

1758
来自专栏Python自动化测试

装饰器的简单应用

在Python的函数中,函数的参数我们成为形式参数,想比较而言,默认参数在实际的应用中更加丰富,还有一种情况就是函数的参数是函数,特别是在接口自动...

502
来自专栏开源优测

[接口测试_B] 14 pytest+requests实战-参数化

上一篇在一个py文件中,写了一堆test_开头的方法,所有数据和用例都在一个py文件中,本篇尝试读取json文件的测试数据,执行用例。

1154
来自专栏技巅

Thrift之代码生成器Compiler原理及源码详细解析3

1726
来自专栏超然的博客

让js调试更简单—console

console上述的集中度支持printf的占位符格式,支持的占位符有:字符(%s)、整数(%d或%i)、浮点数(%f)和对象(%o):

921

扫码关注云+社区