呃,写了这么多年的代码,正则表达式也用了无数次,每次总是记住然后忘记,然后再记住,然后再忘记。周而复始,从来没有真正成为自己的技能。
所以从网上摘抄了点正则表达式的总结,便于自己记忆。
目录
- 正则表达式语法概述
- 界定符
- 语法组成
- 正则表达式数据结构
- 常量字符
- 变量字符
- 简单变量字符
- 字符类变量字符
- 正则表达式逻辑控制
-
- 匹配位置内容判断
- 匹配内容次数控制
- 匹配内容获取与引用
- 匹配模式修正
-
内容
1 正则表达式语法
正则表达式可以看做一种语法经过压缩的程序语言,
可以使用代码注释正则表达式的方法进行学习
1-1 正则界定符
正则表达式使用界定符包围正则字符串作为正则表达式的代码
常见界定符"/","#","~"或者括号对 () [] {}
代码解释:与php的<?php ,?>的开始结束标签相同
/foo bar/ ; "/"界定符
#^[^0-9]$# ; "#"界定符
+test+ ; "+"界定符
%[a-zA-Z0-9_-]% ; "%"界定符
正则字符串中出现界定符时,需要使用反斜线"/"转义处理,
/http:\/\// ;"/"作为界定符,匹配http://时,"/"需要转义
#http://# ;"#"作为界定符,匹配http://时,"/"不需要转义
可以在结束分隔符后面增加模式修饰符
1-2 语法组成
正则表达式中的语法分为数据结构与逻辑控制
数据结构:
1 常量字符串 :普通字符组成
2 变量字符串 :特殊字符组成
逻辑控制:
1 匹配内容获取与引用
2 匹配位置内容判断
3 匹配内容次数控制
4 匹配逻辑或选择
2 正则表达式数据结构
2-1 常量字符串
匹配常量字符串hello
"/hello/"
匹配忽略大小写常量字符串 hello
"/hello/i"
2-2 变量字符串
2-2-1简单变量字符: 使用 带有转义的单个特殊字符表示
\d ;匹配一个数字字符 等价于[0-9]
\D ;匹配一个非数字字符 等价于[^0-9]
\s ;匹配一个任意空白字符 等价于[\n\r\t\v\f]
\S ;匹配一个任意非空白字符 等价于[^\n\r\t\v\f]
\w ;匹配一个字母/数字/下划线/汉字字符 等价于[A-Za-z0-9_]
\W ;匹配一个任意非单词字符 等价于[^A-Za-z0-9_]
. ;匹配一个 除换行\n外的任意字符 等价于[^\n]
\n ;匹配一个换行符 等价于\x0a和\cL
\r ;匹配一个回车符 等价于\x0d和\cM
\t ;匹配一个水平制表符 等价于\x09和\cI
\v ;匹配一个垂直制表符 等价于\x0b和\cK
\f ;匹配一个换页符 等价于\x0c和\cL
匹配数字字符,空白字符,单词字符
"/\d/" , "/\s/" , "/\w/"
2-2-2字符类变量字符: 使用 []格式表示
[xyz] ;匹配xyz其中一个字符
[a-z] ;匹配a到z其中一个字符
[A-Z] ;匹配A到Z其中一个字符
[0-9] ;匹配0到9其中一个字符
[^xyz] ;匹配除xyz以外的一个字符
[^a-z] ;匹配除a到z外的一个字符
3 正则表达式逻辑控制
1 匹配位置内容判断
^x(exp) ;判断字符串第一个字符是否为x if (str.first_letter == x) {匹配}
(exp)$x ;判断字符串最后一个字符是否为x if (str.last_letter == x) {匹配}
\bx(exp) ;判断单词第一个字符是否是x if (word.first_letter == x){匹配}
(exp)y\b ;判断单词最后一个字符是否是x if (word.last_letter == x){匹配}
(?<=exp)x ;匹配前面是exp的x (if x.prev == exp){匹配x}
(?<!exp)x ;匹配前面不是exp的x (if x.prev != exp){匹配x}
x(?=exp) ;匹配后面是exp的x (if x.next == exp){匹配x}
x(?!exp) ;匹配后面不是exp的x (if x.next != exp){匹配x}
多个判断组合
或判断 (?<=bullock|donkey)x 匹配前面是bullock或者donkey的x
且判断 (?<=\d{3})(?<!999)foo 匹配前面是3个数字而且不是999的foo
嵌套判断 (?<=(?<!foo)bar)baz 嵌套判断匹配前面有 ”bar” 但是 ”bar” 前面没有 ”foo” 的 ”baz”。
嵌套判断 (?<=\d{3}…(?<!999))foo 匹配前面有三个数字字符紧跟 3 个不是 999 的任意字符的 ”foo”。
2 匹配内容次数控制
贪婪匹配:尽可能多匹配
x* ;匹配零或多次个x字符 for(i=0;i>=0;i++){匹配x*i}
x+ ;匹配一次或多次个x字符 for(i=0;i>0;i++){匹配x*i}
x? ;匹配零次或一次个x字符 for(i=0;0<=i<=1;i++){匹配x*i}
x{n} ;匹配n次个x字符 for(i=0;i==n;i++){匹配x*i}
x{n,} ;匹配n次或更多次个x字符 for(i=0;i>=n;i++){匹配x*i}
x{n,m} ;匹配n到m次个x字符 for(i=0;n<=x<=m;i++){匹配x*i}
懒惰匹配:尽可能少匹配
x*? ;匹配零或多次个x字符 for(i=0;i>=0;i++){匹配x*i}
x+? ;匹配一次或多次个x字符 for(i=0;i>0;i++){匹配x*i}
x?? ;匹配零次或一次个x字符 for(i=0;0<=i<=1;i++){匹配x*i}
x{n}? ;匹配n次个x字符 for(i=0;i==n;i++){匹配x*i}
x{n,}? ;匹配n次或更多次个x字符 for(i=0;i>=n;i++){匹配x*i}
x{n,m}? ;匹配n到m次个x字符 for(i=0;n<=x<=m;i++){匹配x*i}
3 匹配内容获取与引用
3-1:普通分组
(exp) ;匹配exp变量,并存储到结果分组中
(\d) ;匹配数字分组,并进行存储
((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
;匹配多个分组,并进行存储
3-2: 命名分组
(?<name>exp) ;匹配exp变量,并存储到名称为name的结果分组中
3-3: 一次性分组
(?>exp) ;尽可能长匹配exp变量,不对其内部进行匹配
3-4:条件分组
(?(conditon)yes-pattern|no-pattern)
condition为数字,该数字代表的(之前的)子组得到匹配,使用yes_pattern,否则使用no-pattern
condition为断言,断言成功使用yes-pattern,断言失败使用no-pattern
4 正则模式修正
\i ;忽略大小写
\m ;多行模式
\s ;单行模式