正则表达式
元字符
. [匹配除换行符以外的任意字符]
\w [匹配字母数字下划线或汉字]
\s [匹配任意空白符]
\b [匹配单词的开始或结束]
* [匹配0-n次连续出现的字符]
+ [匹配1-n次连续出现的字符]
? [匹配0-1次出现的字符]
^ [匹配相反的字符]
example:非(提取a标签内容) $reg='#<a[^>]*>([^<>]*)<\/a>#'; $str="<a href='ssss'>some</a>other<a href='ddd'>some</a>"; $res=preg_match_all($reg,$str,$m);
字符组
[] [匹配单个字符,故? * . {}等不需在其中转义]
分支
| [匹配可能存在的多种情况(可以多字符)]*需注意顺序*
分组
(exp) [匹配exp,并捕获文本到自动命名的组里]
(?<name>exp) [匹配exp,捕获到名称为name的组里 | 反向引用中\k<name>]
(?:exp) [匹配exp,但不捕获也不分配组号]
组号分配中,从左到右,先分配无组名的,在分配有组名的
(?=exp) [匹配exp前面的位置]
(?<=exp) [匹配exp后面的位置]
(?!exp) [匹配后面不是exp的位置]
(?<!exp) [匹配前面不是exp的位置]
断言匹配的是一个事实,不是内容
example:数字加千分位 同number_format $reg="#\\d{1,3}(?=(\\d{3})+(?:[.|$]))#"; $str="1234567891238.5646656567"; $res=preg_replace_callback($reg, function($matches){ return ($matches[0].','); },$str); example:否定环视,提取非p标签内的内容 $reg='#<(?!p)([^>\s]+)\s*(?:[^>]+)?>(.*?)</\1>#'; $str="<p>sdfd</p><div>dddiv</div>dom<img src='aaa'/><a href='ssss'>some</a>other"; $res=preg_match_all($reg,$str,$m);
(?#comment) [提供注释以供阅读]
反向引用
\1,\2 ... [用于重复前边匹配到的对应分组内容]
\k<name>或(?P=name) [有组名的反向引用]
example:为了匹配到内容不是 "this is a ' $reg="#(\"|').*?\\1#"; //$reg="#(?P<quote>\"|').*?(?P=quote)#"; $str="\"this is a 'string'\""; preg_match($reg,$str,$m);
懒惰匹配
*? 重复任意次,但尽可能少
example:若无 ?,会一直匹配到结尾的[/url] $reg="#\\[url\\](.*?)\\[\\/url\\]#"; $str="[url]1.png[/url][url]2.png[/url][url]3.png[/url]"; $res=preg_replace($reg,"<img src='$1'/>",$str);
模式
- 忽略大小写
#...#i [全局]
(?i)c [局部,对其后字符影响]
- 忽略大小写
多行模式
#...#m [每一行都单独去匹配,另外,$默认表示最后一行]
-点号通配模式
- #...#s [使其中的.可以通配换行符,达到跨行效果,多用于大段文字匹配]
懒惰模式
#...#U [同懒惰字符?]
结尾限制
#...#D [有$存在是结尾不可有\n]
支持UTF-8转义表达
#...#u [对模式中字符串当做utf8]
example:utf8中文检测 $str="php百度"; $reg='#^[\x{4e00}-\x{9fa5}]+$#u'; if(preg_match($reg,$str,$m)){ echo '全部为中文'; }else{ echo '不全是中文'; }
优化正则
- 使用字符组代替分支条件
- [a-c]比(a|b|c)效率高
- 相同开头分支条件,优先放有不同处的分支在前边
- 如邮编匹配,三位或四位区号
- 标准量词是匹配优先的
\w*(\d+)去匹配copy2003y,匹配结果会是3,因为\w*贪婪匹配到整个字符串,然后\d+匹配不到,会书到3才结束,要改为懒惰模式\w*?
- 能确定范围就不要用 “.”,能确定重复次数就不要用 “*” 或 “+”,能用懒惰就不用贪婪模式
- 合理使用(),对于不需要捕获的尽量使用(?:…)
- 起始、行描点优化,加上^,$,并尽量与分组分离
- 对大而全的正则拆分
- 优先使用php内置函数代替正则
- 输入的校验用filter更合理filter_var(‘admin@qq.com’,FILTER_VALIDATE_EMAIL)
- 分析源代码tokenizer
如有疑问,请文末留言交流或邮件:newbvirgil@gmail.com 本文链接 : https://newbmiao.github.io/2015/02/28/regex-notes.html