BeWithYou

胡搞的技术博客

  1. 首页
  2. PHP
  3. 关于正则表达式

关于正则表达式


不知道放到哪个分类里,先放到PHP这里吧。后续可能会慢慢修改增加。

正则表达式中一些需要注意的地方

  • . 匹配除了换行符”\n”以外的所有字符。

  • […]中如果第一个字符是^表示取反

  • \d数字 \D非数字 \s空白 \S非空白 \w包括字母和数字 \W非单词

  • {m,n} 匹配前面的字符从m到n次。如果m省略,则匹配0到n,省略n则匹配m到无限次。

  • ^匹配字符串开头 多行模式中匹配每一行开头

  • $匹配字符串结尾 多行模式中匹配每一行结尾

  • | 左右任意匹配一个。先看左边的,匹配了则跳过右边的。如果|没有用()包起来,则范围是整个正则表达式。如 ab|cd 匹配ab和cd a(b|c)d匹配abd和acd。^ab|cd$,实际上是(^ab|cd$)即ab开头或cd结尾,因为|的优先级很低。

  • (…) 分组。从左边开始每遇到一个左括号(,编号+1。后面引用的时候可以用\1 来表示。 比如 (\d)abc\1 匹配1abc1 不匹配 1abc2

  • (?P<name>…) 和 (?P=name) 给分组起名字和引用分组,只有python中才有。

  • \0的引用分组是默认存在的,对应整个表达式匹配的文本。

  • 我们一般用的是PCRE流派的正则规范,unix系统中使用的是POSIX规范的,字符组中存在差异。像\d这种简写不可用了,可以用[:digit:]这种。

  • .*的贪婪匹配 当不知道当前字符是否需要匹配的时候,先算匹配。等到字符串结束了,正则表达式里还有没有匹配到的字符,则回溯。

  • 忽略优先量词,比如<script type="text/javascript">[\s\S]*\</script> 这种可能会匹配超过两段js代码进来。 然而我们也不能用[^</script>]来去除一个字符串。我们可以用“忽略优先量词”的方式。与上面贪婪匹配相反,在不知道一个字符是否需要匹配的时候,我们先不匹配,往下一个字符看,如果下一个字符不匹配,则回溯过来。比如<script type="text/javascript">[\s\S]*?</script> 用*?代替*,表示忽略优先量词。当匹配到一段js代码,即</script>之前的那个字符,此时先不用[\s\S]*?匹配他,而是看*?后面的</script>能不能匹配他,发现不能匹配。于是用[\s\S]*?匹配他。之后发现了后面的</script>可以用</script>来匹配,则走过[\s\S]*?,使用</script>来匹配了。 有效防止了错误匹配多段js代码。

  • 量词需要转义,也用\。 比如{m,n} 用一个\即可。但是*?这种 需要变成*\?,用两个。

  • 反响引用\num,可能存在二义性。比如\10,本意是第一个分组后面跟着字符0,但是会被解释成第10个分组匹配的文本。PHP中有${1}0可以解决这个问题,同样python中也有\g<1>0的方法。并不是所有语言都有解决方法,需要注意。尽量减少分组数目。

  • 某些情况,我们用小括号只是为了单纯的聚合元素,并不是为了捕获分组。此时可以声明为非捕获分组,如(?:\d),这里的\d不算在捕获分组里。

  • 单词边界断言\b,行边界断言^,$。如果是多行模式, ^$z则可作为每行的起始结束定位符。多行模式设定方法为在表达式开头加上(?m)。如"(?m)^\w+",匹配每行的第一个单词。

  • 环视可以用来判断某个字符左右是否出现特定字符,比如(?!/),限定前面的字符往右不能出现/。而且它不会占用匹配文本的位置。例如,<[^/]中的[^/],本意是限定<后面不能出现/,但是[^/]已经占了一个字符的位置,所以它可以匹配<a。但是<(?!/)中,环视不会包含多余的字符,他只匹配<。

  • 肯定顺序环视(?=...) 否定顺序环视(?!...) 肯定逆序环视 (?<=...) 否定逆序环视(?<!...)
回到顶部