目录
在学习反序列化时遇到了preg_match这一个函数,经过学习发现是有关正则表达式的函数,于是学一下正则表达式。贴上学习网址
正则表达式主要用于搜索,替换,提取某个字串。相较于kmp算法这类典型的匹配模式,正则匹配更加灵活,不需要完全确定所需字串内容可以模糊搜索。例如可以使用[0-9]来表示包含数字[a-z]来表示包含小写字母。这里总结一下正则表达式的基本语法。
一.普通字符(在这里例子都加了修饰符g)
1.[ABC] 匹配原字符串中所有包含的字母 例:
[aeiou] 匹配了字符串中所有元音字母。
2.[^ABC] 匹配除了ABC的其他所有字母
(但这里的^在不同情况下有不同的作用,这点留到最后讨论)
3.[A-Z] 表示匹配在这个区间内的所有字符,可以是大小写字母,数字等
4. . 例如:/. /g 匹配除换行符之外的所有单个字母
5.[\s\S] 匹配所有。/s为匹配所有空白符包括换行,/s为非空白符不包括换行。
6.\w 匹配字母,数字,下划线。
二.非打印字符
也就是一些系统需要用到的但不会显示给用户的字符。这里不多叙述 主要包括\cx \f \n \r \s \S \t \v 等。
三.特殊字符
这个感觉要详细记录一下。
$ | 匹配结尾位置字符,例如/a$/会匹配以a为结尾的字符。 |
() | 主要用来分段或分支,类似与运算中的括号,例如:/(ab)* 匹配ababab这样的字符串,而/ab* 匹配abbbb这样的。 |
* | 匹配前面的字符零次或多次。 |
+ | 匹配前面的字符一次或多次。与*的区别在于/ab*匹配abb或a,/ab+匹配ab,abbb等而不能匹 配a。 |
. | 匹配单个字符(除\n换行符) |
[ | ]表示匹配的字符在[]中,并且只能出现一次,并且特殊字符写在[]会被当成普通字符来匹配。例 如[(a)],会匹配(、a、)、这三个字符。 |
? | 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。 |
\ | 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配 字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。 |
^ | 匹配输入字符串的开始位置,除非在方括号表达式中使用,当该符号在方括号表达式中使用时, 表示不接受该方括号表达式中的字符集合。例如[^a]表示匹配非a的所有字符,/^a表示以a为头 |
{ | 表示限定表达式, |
| | 等同于或,例如/^aaaaa|^abcs表示以aaaaa开头或abcs开头 |
四.限定符
* + ?之前已经提到过,这里再记录{n}, {n, },{n,m}
{n} | n为非负整数,表示匹配确定的n次,比如o{2}只能匹配book之类的字符串 |
{n, } | n为非负整数,表示至少匹配n次 例:o{2,}不能匹配bok但能匹配booook |
{n,m} | m,n都为非负整数,n<=m,表示至少匹配n次,最多m次 |
这里还有一个贪婪和非贪婪的概念,比如+ *就是贪婪的,因为它们可以取后无数的字符,而?只能匹配0或1次,也就不是贪婪的。
五.定位符
^和$表示字符串开始和结束,前面已经描述过,这里不再赘述。除此之外还有\b \B
\b | 匹配一个单词边界,例如/\bling/能匹配lingko,/ling\b/匹配koling。 |
\B | 匹配非单词边界,例如/\Boki/能匹配bokiaaa,但不能匹配boki,因为此时oki在单词边界。 |
六.选择
在这里不知道为什么要叫选择,但是大体原理还是知道了,使用()时会造成缓存,而这个缓存有可能被用来攻击也会占用内存,所以需要用到选择。
例如/([0-9])(1abandon)/可以在1323aba21abadon里查出1abandon但会有缓存,如果使用选择,那么可以直接使用/(?<=[0-9]+)1abandon/查出1abandon而没有缓存。这里记录?=,?<=,?!,?<!的区别
?= | exp1(?=exp2) 查找exp2前的exp1 |
?<= | (?<=exp2)exp1:查找 exp2 后面的 exp1 |
?! | exp1(?!exp2):查找后面不是 exp2 的 exp1 |
?<! | (?<!exp2)exp1:查找前面不是 exp2 的 exp1 |
七.反向引用
在我的理解下就是通过拆分多个匹配条件来获得几个数据,而这种切分通过()和str.match函数实现。这里借用菜鸟教程上的代码分析一下。
var str = "https://www.runoob.com:80/html/html-tutorial.html";
var patt1 = /(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/;
arr = str.match(patt1);
for (var i = 0; i < arr.length ; i++) {
document.write(arr[i]);
document.write("<br>");
}
str.match()返回一个数组,包含五个元素,第一个是整个字符串,第二个是第一个括号内所匹配的值,第三个元素是第二个括号以此类推;
而此时通过匹配条件可知
- 第一个括号子表达式包含 http
- 第二个括号子表达式包含 www.runoob.com
- 第三个括号子表达式包含 :80
- 第四个括号子表达式包含 /html/html-tutorial.html
总结
正则匹配在很多语言里都有,学了总不吃亏。但正则匹配还有一些修饰符和元字符这次没有总结,运算符的优先级也比较重要。不过这些在菜鸟教程上都有,也就不加了。
附言
下一篇回归正题,总结一下反序列化的知识点吧。
希望自己不要这么菜吧 _(:з」∠)_ ----L1men2