前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >正则表达式学习笔记

正则表达式学习笔记

作者头像
用户1327360
发布2018-03-07 14:54:39
1.2K0
发布2018-03-07 14:54:39
举报
文章被收录于专栏:决胜机器学习决胜机器学习

正则表达式学习笔记

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

首先,学习正则表达式,很推荐一篇博客,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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 决胜机器学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档