regex_note
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了regex_note相关的知识,希望对你有一定的参考价值。
# 正则表达式
# 元字符
对于字符串"DEF",在正则中视为包含3个字符"D","E","F"和4个位置0-3,"DEF"= 0D1E2F3.
如果子表达式匹配到东西,而不是一个位置,并最终保存到匹配的结果中.这样的就称为占有字符.占有字符是互斥的,即一个字符,同一时间只能由一个子表达式匹配。
而只匹配一个位置,或匹配的内容并不保存到匹配结果中,这就称为零宽度.零宽度是非互斥的,即一个位置,可以同时有多个零宽度的子表达式匹配.
# 元字符 描述
\b 匹配单词的开始或结束
\w 匹配字母或数字或下划线或汉字
\s 匹配任意空白符,包括空格,TAB,换行符等
\d 匹配任意数字
. 匹配出换行符外任意字符
^ 匹配字符串的开始
$ 匹配字符串的结束
# 字符转义
如果想查找元字符本身,需要使用‘\‘来转义.如: \.
# 重复 描述
* 重复0次或多次
+ 重复1次或多次
? 重复0次或1次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
例如: \d{5,12} 匹配了5到12位的连续数字.
# 字符类 描述
[] 方括号中列出匹配字符的集合
例如: [0-9] 表示匹配一位数字
# 分支条件描述
| 符号‘|‘把不同规则隔开
例如: \d{5}-\d{4}|\d{5} 可以匹配连字符间隔的9位数字或5位数字.值得一提的是要注意各个条件的顺序.因为匹配分枝条件时,会从左到右的匹配,如果满足了某个分支,就不会再管其它条件了.
# 分组 描述
() 括号里的子表达式被作为一组
例如: (\d{1,3}\.){3} 匹配出现3次的(\d{1,3}\.)
# 反意 描述
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意不是数字的字符
\B 匹配任意不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeio] 匹配除了aeio这几个字符的任意字符
# 后向引用
使用小括号指定一个子表达式后,匹配到的内容可以用于进一步处理,默认情况下,每个分组会自动拥有一个组号,依次为1,2,3... 另外,分组0对应整个正则表达式.
使用\1代表分组1匹配的文本.如: \b(\w+)\b\s+\1\b 这可以用来匹配重复的单词.
语法 描述
(exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名为name的组里,也可以写成(?‘name‘exp)
调用有名字的组可以使用\k<name>
(?exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
# 注释
语法 描述
(?#comment) 这种类型的分组不对正则表达式的处理产生影响,用于提供注释
要包含注释的话,最好是启用“忽略模式里的空白符”选项,这样在编写表达式时能任意的添加空格,Tab,换行,而实际使用时这些都将被忽略。启用这个选项后,在#后面到这一行结束的所有文本都将被当成注释忽略掉。
例子:
(?<= #断言要匹配的文本的前缀
<(\w+)> #查找尖括号括起来的字母或数字(即html/XML标签)
) #前缀结束
.* #匹配任意文本
(?= #断言要匹配的文本的后缀
<\/\1> #查找尖括号括起来的内容:前面是一个"/",后面是先前捕获的标签
) #后缀结束
# 零宽断言
零宽断言: 用于指定一个位置,并且这个位置满足一定的条件(即断言).
语法 描述
(?=exp) 匹配exp前面的位置,即断言自身后面能匹配表达式exp
(?<=exp) 匹配exp后面的位置,即断言自身前面能匹配表达式exp
(?!exp) 匹配后面不是exp的位置
(?<!exp) 匹配前面不是exp的位置
# 贪婪和懒惰
当正则表达式中包含能接受重复的限定符时,通常的行为是匹配尽可能多的字符.如a.*b,将会匹配最长的以a开始,以b结束的字符串,若搜索aabab时,它会匹配整个字符串aabab.这是贪婪匹配.
有时,我们需要懒惰匹配,就是匹配尽可能少的字符.只要在重复表达式后面加上一个问号.如: a.*?b 匹配以a开始,以b结束的字符串.若搜索aabab,它会匹配aab和ab.
常用懒惰限定符
*?, +?, ??, {n,m}?, {n,}?
# 正则表示式处理选项
忽略大小写 匹配时不去分大小写
多行模式 更改^和$的含义,使它们分别匹配每行的行首和行尾
而不是仅在字符串的开始和结束匹配
单行模式 更改.的含义,使它也能匹配换行符\n
忽略空白 忽略表达式中的非转义空白,并启用由#标记的注释
显式捕获 仅匹配已被显式命名的组
# 平衡组/递归匹配
应用场景:(100*(50+15)) 或 (5/(3+2)))
递归配对用于解决括号配对问题.
(?‘group‘) 把捕获的内容命名为group,并压入堆栈(Stack)
(?‘-group‘) 从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败
(?(group)yes|no) 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分
(?!) 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败
我们需要做的是每碰到了左括号,就在压入一个"Open",每碰到一个右括号,就弹出一个,到了最后就看看堆栈是否为空--如果不为空那就证明左括号比右括号多,那匹配就应该失败。正则表达式引擎会进行回溯(放弃最前面或最后面的一些字符),尽量使整个表达式得到匹配。
< #最外层的左括号 [^<>]* #最外层的左括号后面的不是括号的内容
( ( (?‘Open‘<) #碰到了左括号,在黑板上写一个"Open"
[^<>]* #匹配左括号后面的不是括号的内容 )+ ( (?‘-Open‘>) #碰到了右括号,擦掉一个"Open"
[^<>]* #匹配右括号后面不是括号的内容 )+ )* (?(Open)(?!)) #在遇到最外层的右括号前面,判断黑板上还有没有没擦掉的"Open";如果还有,则匹配失败 > #最外层的右括号
平衡组的一个最常见的应用就是匹配HTML,下面这个例子可以匹配嵌套的<div>标签:<div[^>]*>[^<>]*(((?‘Open‘<div[^>]*>)[^<>]*)+((?‘-Open‘</div>)[^<>]*)+)*(?(Open)(?!))</div>.
以上是关于regex_note的主要内容,如果未能解决你的问题,请参考以下文章