标签:失败 hat 入门 字符 book 堆栈 最好 说明 要求
代码 | 说明 |
---|---|
* | 重复 0 次或者重复多次 |
+ | 重复 1 次或者重复多次 |
? | 重复 0 次或者 1 次 |
{n} | 重复了 n 次 |
{ n, } | 重复了 n 次或者更多次 |
{m,n} | 重复 m 到 n次 |
使用中括号 []
[aeiou]
匹配任何一个元音字母[.?!]
匹配标点符号 . ? ![0-9]
匹配数字 0-9 与 \d
代表的意义相同[0-9a-zA-Z]
与 \w
等价\(?0\d{2}[(-]?\d{8}
首先是一个转义字符\(
它出现0次或1次(?
), 然后是数字 0,后面跟着 2 个数字 (\d{2}
), 然后是空格或者-
中的一个,它出现1次或者不出现(?
),最后是8个数字(\d{8}
) 。上式可以匹配010)88886666,或022-22334455,或02912345678等常见电话号码格式,但是也能匹配 010)12345678或(022-87654321这样的“不正确”的格式,因此就要使用下面的 分支条件
用|
号把不同的规则分隔开
e.g. \(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}
这个表达式匹配三位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号支架你可以用连字号或空格间隔,也可以不用。
注意: 匹配分支条件时,将会从左到右地测试每个条件,如果满足了某个条件将不会再去管其他的条件
比如:\d{5}-\d{4}|\d{5}
用于匹配美国的邮政编码,美国邮编的规则是5位数字或者用连字号间隔的9位数字;如果写成:
\d{5}|\d{5}-\d{4}
那么就只会匹配5位的邮编,以及9位邮编的前五位
e.g. 描述一个IP地址
((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
要点:2[0-4]\d|25[0-5]|[01]?\d\d?
分为三种情况:
\.
表示IP四个数字之间的分隔,由于最后面一个数字不带点,所以要分开,先写前面3个{3}
代表前面的部分重复三次采用大写的方式,与原来的小写方式表达相反的含义
|代码|说明|
|:-:|:-:|
|\W
| 与\w
相对应,匹配不是字母、数字、下划线的字符
|\S
|与\s
相对应,匹配任何不是空白符的字符
|\D
|与\d
相对应,匹配任意非数字的字符
|\B
|与\b
相对应,匹配不是单词开头或结束的位置
|[^x]
|匹配除x
以外的字符
|[^aeiou]
|匹配除aeiou以外的任意字符
使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。
后向引用用于重复搜索前面某个分组匹配的文本,\1
代表分组1匹配的文本
e.g.
\b(\w+)\b\s+\1\b可以用来匹配重复的单词,像go go, 或者kitty kitty。这个表达式首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(\b(\w+)\b
),这个单词会被捕获到编号为1的分组中,然后是1个或几个空白符(\s+
),最后是分组1中捕获的内容(也就是前面匹配的那个单词)(\1
)。
也可以自己指定表达式的组名,e.g.指定一个表达式的组名为Word
,则可以使用 (?<Word>\w+)
,其中尖括号也可以用引号 ‘
来替代,即(?‘Word‘\w+)
,当反向需要引用这个分组捕获的内容时,可以用\k<Word>
代码 | 说明 |
---|---|
(exp) |
匹配 exp ,并捕获文本到自动命名的组里 |
(?<name>exp) |
匹配 exp ,并捕获文本到名称为 name 组里,也可以(?‘name‘exp) |
?:exp |
匹配 exp ,不捕获匹配的文本,也不给此分组分配组号 |
(?=exp)
它断言自身出现的位置后面可以匹配表达式 exp ,比如:\b\w+(?=ing\b)
匹配以 ing 结尾的单词的前面部分(除了 ing 以外的部分),比如在查找 I am singing while you are dancing. 它会匹配 sing 和 danc,称之为:零宽度正预测先行断言(?<=exp)
它断言自身出现的位置前面可以匹配表达式 exp ,比如 (?<=\bre)\w+\b
,会匹配以 re 开头的单词的后半部分(除 re 以外的部分),比如在查找 reading a book ,会匹配 ading。称之为零宽度正回顾后发断言e.g. (?<=\s)\d+(?=\s)
匹配以空白字符间隔的数字(不包括这些空白字符)
(?!exp)
断言此位置的后面不能匹配表达式 exp
e.g.
\d{3}(?!\d)
匹配三位数字,而且这三位数字的后面不能是数字
\b((?!abc)\w)+\b
匹配不包含连续字符串 abc 的单词
一个更复杂的例子:(?<=<(\w+)>).*(?=<\/\1>)
匹配不包含属性的简单HTML标签内的内容;(?<=<(\w+)>)
指定了这样的前缀:被尖括号括起来的单词;然后是.*
,即任意字符串,最后是一个后缀?=<\/\1>
,这里\/
(斜杠和反斜杠)b用到了前面的字符转义;\1
用到了反向引用,引用的正是捕获的第一组\w+
匹配的内容,这样,如果前缀是, 那后缀就是 ;整个表达式匹配的是和之间的内容(不包括前缀和后缀)
?#comment
来包含注释,例如:2[0-4]\d(?#200-249)|25[0-5](?# 250-255)|[01]?\d\d?(?#0-199)
(?<= #断言要匹配的文本的前缀
<(\w+)> #查找尖括号括起来的字母或数字(即HTML或XML标签)
) #前缀结束
.* #匹配任意文本
(?= #断言要匹配的文本的后缀
<\/\1> #查找尖括号括起来的内容
) #后缀结束
a.*b
将匹配 最长的以 a 开始,以 b 结束的字符串,如果用其来搜索 aabab 它会匹配整个字符串;这被称之为 贪婪匹配,匹配?
,即.*?
表示匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复;a.*?b
匹配最短的,以 a 开始,以 b 结束的字符串;如果将其应用于 aabab,它会匹配到第一个aad(第1个字符到第3个字符)和 ab (第4-5个字符)
代码 | 说明 |
---|---|
*? |
重复任意次,但是尽可能少的重复 |
+? |
重复1次或更多次,但尽可能少的重复 |
?? |
重复0次或1次,但尽可能少重复 |
{m,n}? |
重复 m-n 次,但是尽可能少重复 |
{n,}? |
重复n次以上,但是尽可能少重复 |
有时我们需要匹配像( 100 * ( 50 + 15 ) )这样的可嵌套的层次性结构,这时简单地使用(.+)则只会匹配到最左边的左括号和最右边的右括号之间的内容(这里我们讨论的是贪婪模式,懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次数不相等,比如( 5 / ( 3 + 2 ) ) ),那我们的匹配结果里两者的个数也不会相等。有没有办法在这样的字符串里匹配到最长的,配对的括号之间的内容呢?
为了避免(和(把你的大脑彻底搞糊涂,我们还是用尖括号代替圆括号吧。现在我们的问题变成了如何把xx <aa
(?‘group‘)
把捕获的内容命名为group,并压入堆栈(stack)(?‘-group‘)
从堆栈上弹出最后压入堆栈的名为 group 的捕获内容,如果堆栈为空,则本组的匹配失败(?(group)yes|no)
如果堆栈上存在以名为group的不捕获内容的话,继续匹配 yes 部分的表达式,否则匹配 no 部分(?!)
零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败思路:每碰到左括号,就压入一个 "Open" ,每碰到一个右括号,就弹出一个,到了最后看堆栈是否为空,如果不为空则证明左括号比右括号多,那匹配就应该失败。正则表达式会进行回溯(放弃最前面或最后面的一些字符),尽量使整个班表达式得到匹配
< #最外层的左括号
[^<>]* #最外层的左括号后面的不是括号的内容
(
(
(?‘Open‘<) #匹配到了左括号,往堆栈压入一个‘Open‘
[^<>]* #匹配左括号后面不是括号的内容
)+ #可以出现多次
(
(?‘-Open‘>) #碰到了右括号,则从堆栈弹出一个‘Open‘
(^<>)* #匹配右括号后面不是括号的内容
)+ #可以出现多次
)* #整个上面可以出现多次
(?(Open)(?!)) #在遇到最外层的右括号前面,判断堆栈上是否还有"Open",
#如果还有,则执行 (?!),由于后面没有后缀表达式,匹配总是失败
> #最外层的括号
标签:失败 hat 入门 字符 book 堆栈 最好 说明 要求
原文地址:https://www.cnblogs.com/qiulinzhang/p/9513547.html