正则表达式常用元字符
. 匹配除换行符以外的任意字符
匹配英文单词的开始和结束,只是匹配一个位置
d 匹配一个阿拉伯数字,多个数字可以这样 d{3} 3个连续的数字
w 匹配字母或数字或下划线或汉字
s 匹配任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格等。
* 表示前边的内容可以连续重复使用任意次以使整个表达式得到匹配
+ 匹配重复1次或更多次
^ 匹配你要用来查找的字符串的开头,
$ 匹配字符串的结尾,例如:QQ号必须为5位到12位数字时,可以使用:^d{5,12}$
? 重复零或一次
{n} 重复n次
{n,} 重复n次或更多
{n,m} 重复n至m次
分枝条件符号 | :
d{5}-d{4}|d{5}这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字
分组符号 () :
d{1,3}.){3}d{1,3}是一个简单的IP地址匹配表达式。可能出现 999.999.999.999
更好的描述
((2[0-4]d|25[0-5]|[01]?dd?).){3}(2[0-4]d|25[0-5]|[01]?dd?)
反义:
W 匹配任意不是字母,数字,下划线,汉字的字符
S 匹配任意不是空白符的字符
D 匹配任意非数字的字符
B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符
后向引用:
用于重复搜索前面某个分组匹配的文本,1代表分组1匹配的文本
(w+)s+1可以用来匹配重复的单词,像go go, 或者kitty kitty
自己指定子表达式的组名:
(?<Word>w+)(或者把尖括号换成'也行:(?'Word'w+)),这样就把w+的组名指定为Word了
上一个例子也可以写成这样:(?<Word>w+)s+k<Word>
捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言
(?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
注释(?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读
(?=exp) 也叫零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp
w+(?=ing) 查找I'm singing while you're dancing.时,它会匹配sing和danc。
(?<=exp) 也叫零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp
(?<=re)w+ 查找reading a book时,它匹配ading
(?!exp) 零宽度负预测先行断言,断言此位置的后面不能匹配表达式exp。只匹配一个位置,并不消费任何字符
区别[^x]
((?!abc)w)+匹配不包含连续字符串abc的单词
一个更复杂的例子 (?<=<(w+)>).*(?=</1>)匹配不包含属性的简单HTML标签内里的内容
如:<b>和</b>
注释:
(?<= # 断言要匹配的文本的前缀
<(w+)> # 查找尖括号括起来的字母或数字(即HTML/XML标签)
) # 前缀结束
.* # 匹配任意文本
(?= # 断言要匹配的文本的后缀
</1> # 查找尖括号括起来的内容:前面是一个"/",后面是先前捕获的标签
) # 后缀结束
贪婪与懒惰
当正则表达式中包含能接受重复的限定符时,
通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符
a.*b 来搜索aabab的话,它会匹配整个字符串aabab
懒惰匹配,也就是匹配尽可能少的字符
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
a.*?b匹配aabab 找到aab(第一到第三个字符)和ab(第四到第五个字符)
平衡组/递归匹配
(?'group') 把捕获的内容命名为group,并压入堆栈(Stack)
(?'-group') 从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败
(?(group)yes|no) 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分
(?!) 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败
< #最外层的左括号
[^<>]* #最外层的左括号后面的不是括号的内容
(
(
(?'Open'<) #碰到了左括号,在黑板上写一个"Open"
[^<>]* #匹配左括号后面的不是括号的内容
)+
(
(?'-Open'>) #碰到了右括号,擦掉一个"Open"
[^<>]* #匹配右括号后面不是括号的内容
)+
)*
(?(Open)(?!)) #在遇到最外层的右括号前面,判断黑板上还有没有没擦掉的"Open";如果还有,则匹配失败
> #最外层的右括号