最近在学习正则表达式,发现原来理解的正则表达式不是特别的准确,甚至有误!在这里简单记录一下,希望对有的朋友能够有所帮助!
①“[]”:字符集(字符簇,字符组……)
他的真正含义是"或"的意思!例如:[123],它代表的含义是,匹配一个1或2或3!由于它经常是用于匹配多个可能的值,所以支持一种简写的方式! 例如:[12345678]可以简写为[1-8]
[abcdefghjik]可以简写为[a-k] [1234567ABCDEFG]可以简写为[1-7A-G]
“[]”相关的陷阱!
(1)在”[]”中的大部分元字符都是普通字符,都不在具有元字符的含义!但是仍然有个别的元字符除外!
“-”,“^”,目前只知道这两个,可能还有其他的,待补充!“-”,是作为连字符表示的是一个范围,
- 如果单独的将“-”符号放在第一位的话,它表示的也是一个普通的字符!例如:[a-z]这个时候就是元字符,代表的是一个范围!
- 在[-abc]中,"-"就是一个普通的字符,这句话就表示,匹配-、a、b、c中,这四个字符中的任意一个!
^有两个意思,
- 在字符簇外,它表示的是托字节,匹配的是一个位置!
- 而在字符簇中相当于取反的意思!而且只有当托字节放在字符簇的第一个位置的时候才会表示一个元字符!
<?php
$str =<<<STR
Iraq
Iraqian
miqra
qintar
aoph
zaqqnum
STR;
$reg = '/q[^udfg]/';
preg_match_all($reg, $str, $result);
var_dump($result);
运行结果如下
array(1) { [0]=>array(5) { [0]=> string(2) "q " [1]=> string(2) "qi"[2]=> string(2) "qr" [3]=> string(2) "qi" [4]=>string(2) "qq" } }
?>
可能会有的朋友问Iraq中q后面匹配了什么!答案是回车(在window状态下是\r\n)!\r并不属于udfg中的任意字符所以匹配成功! 在heredoc的语法中,会完整的保留空格、制表符、回车换行!
②“|”表示或的意思!它代表一个分支语句!
到这里,可能有的朋友会问,那他的功能岂不是和 ”[]” 的功能重复了么?答案显然是否定的!个人认为“|”,分支语句,在一定程度上弥补了“[]”符号功能的不足!因为“[]”,自始至终只能表示一个字字符!
例如:[a-z],他表示的匹配a-z中的任意一个字符!
而当我们需要匹配abc或def的时候,显然”[]”是无能为力的!而此时也正是“|”分支结构的用处!可以写成(abc|def)
表示匹配abc或者def这两个字符集中的一个!
③“?”表示可选项!它只作用于之前紧邻的元素!
这里我们需要明白一下元素的概念!所谓元素还包括如下的形式:[a-z]这个字符簇整体表示一个元素!(abc|def)这个分支结构整体表示一个元素!
注意:所有的量词都是仅作用于之前紧邻的元素!
④正则中的反向引用
在正则表达式中,使用”()”包裹起来的元素被统一称为子表达式!而括号是能够记忆“()”匹配到的内容的,无论这些匹配到的文本是什么!(这个也就是我们常说的反向引用!如果他是第一个的话使用1,就可以获得字表达式中的内容!)
那么如果判断是表达式几呢?有一个原则:按照开括号“(”从左到右的出现顺序进行计算!依次就是1,2,3…… 注意:反向引用应该是可以嵌套的!遵循的同样是这个原则!看代码:
<?php
$content = 'maweibin is the author';
$regexp = "/(((ma)wei)bin)/";
preg_match($regexp, $content, $result);
var_dump($result);
运行结果如下:
array(4) { [0]=> string(8) "maweibin" [1]=> string(8) "maweibin" [2]=> string(5) "mawei" [3]=> string(2) "ma" }
?>
通过结果,我们可以看到,第一个字表达式是“maweibin”,第二个字表达式是“mawei”,第三个字表达式是“ma”。
⑤正则表达式中的“$”陷阱!
在正则表达式中“$”符号,同托字节“^”一样是匹配一个位置的!但是“$”符号本身又有一些陷阱需要我们注意!
一般情况下,我们都认为“$”符号匹配就是一行中的最后一个位置!这个并没有错,但是不够详细!
其实$匹配的是这样一个位置,匹配n前或单行字串的结束位置,单行字符串结尾什么都没有!举例说明:
<?php
$str =<<<STR
the theory
my myselef
your yourselef
STR;
$reg = '/^([a-zA-Z]+)\s*\1[a-zA-Z]*$/m';
preg_match_all($reg, $str, $result);
var_dump($result);
运行的结果如下array(2) { [0]=> array(1) { [0]=>string(14) "your yourselef" } [1]=> array(1) { [0]=> string(4)"your" } }
?>
只有最后一个被匹配到了! 、
原因是这样的!在window中每换一行会有隐藏字符“\r\n”存在!
$匹配\n前或字串结尾(字符串结尾,比如单独一行的最后),\r 也是一个字符,且不在[a-zA-Z]范围!其实,我们只需要将正则改写为'/^([a-zA-Z]+)\s*\1[a-zA-Z] \s$/m',这里只是加上了一个s*用来匹配r这个看不见的字符串!
⑥关于正则表达在多行匹配中的应用!
正则表达式大多数情况下是进行单行的匹配的!但是,有时候我们也需要进行多行的匹配,特别是在我们进行信息采集的时候,显得就尤为重要!
个人认为,在php中如果我们能够灵活的运用php的模式修饰符,那么多行匹配就没有什么问题了!所以多行匹配,个人认为就是重点对模式修饰符的学习!(1)m(mutiline),加上了m修饰符号的主要作用是更改了托字节”^”和“$”的应用范围!
黑色箭头代表的是托字节”^”所匹配的位置,蓝色箭头是美元符号”%”所匹配的位置! 举例说明:
从上面,我们可以看出来:在没有m修饰符的时候,托字节^仅匹配字符串的开始位置,
而$仅匹配字符串的末尾,或者最后的换行符号!
加上了m修饰符之后:
从上面,我们可以看出来:加上m修饰符后,托字节^会匹配目标字符串的开始,或者任意换行符n前面的位置; 而$会匹配目标字符串的最末位置,或者任意换行符后面的位置!
(2)S修饰,如果设置了这个修饰符那么,模式中的元字符 “ . ” 就会匹配所有字符, 包含换行符. 如果没有这个修饰符, 那么 “ . ”实际上匹配的是除了换行符n外的任意字符!(3)U(这个是大写的ungreedy:非贪婪)。
举例说明: <a href=’www.baidu.com’>百度</a><a href=’www.google.com’>谷歌</a> 正则如下:<a\s*href\s*=\s*’www\.baidu\.com’>.*</a>结果是把全部的字符串都匹配到了!其实,我们只需要加上U修饰符,这样,这样一旦成功匹配一次的话,正则就不会继续进行匹配了!
(4)i(个人认为应该是ingnore的意思),表示在匹配的时候忽略大小写。
⑦最左端文本优先匹配 && 标准的匹配量词是匹配优先的
好抽象,还是举个例子吧:
文本:this is March, March1998
正则:March[0-9]+
匹配过程:
1. 正则中的一个字符M从文本对最左面开始尝试匹配,发现第一个字符是t,并不匹配,换到下一个字符h仍不满足,于是继续下一个字符,直到遇到第一个大写字符M;
2. 正则中第二个字符a, 从M字符后面继续开始匹配,同样满足,于是r字符。就这样,March单词在文本中都得到了匹配。直到遇到了[0-9]+
3. 此时,由于标准匹配量词优先原则,先检测到了+, 声明了在接下来对匹配中,前面对字符要尝试匹配1次到任意对多次
4. 此时,发现 " , " 字符并不满足数字至少出现一次对需求,所以本轮匹配失败,接着来吧。
5. 接着字符 " , ", 接着往下匹配M字符不符合空格,接着下一个字符。发现M字符得到了匹配,紧接着a字符 r字符 c字符 h字符。此时接下来要执行的步骤同步骤3一模一样,这次得到了满足。
![图片上传中...]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。