正则表达式在执行时进行逐个匹配,通常由一些字母和数字组合而成。
例如:正则表达式 The 在匹配时,先匹配字母T,如果T满足匹配借着匹配h,前面都满足再接匹配e。对于正则表达式“sun”的匹配方式,同上。
“The”
The morning sun never lasts a day.
“sun”
The morning sun never lasts a day.
正则表达式大小写敏感的,所以the不会匹配The。
“the”
The morning sun never lasts a day.
标志也叫模式修正符,用来决定正则的匹配模式。
标志 | 英文全称 | 描述 |
---|---|---|
i | insensitive | 忽略大小写。 |
g | global | 全局搜索。 |
m | multi line | 多行修饰符:锚点元字符 ^ $ 工作范围在每行的起始。 |
/abc/i
可以匹配 abc、aBC、Abc 等等/.(at)/g
表示搜索 任意字符(除了换行与空格)+ at,并返回全部结果。“/.(at)/g
” => The fat cat sat on the mat.(^,$)
用于检查格式是否是在待检测字符串的开头或结尾。但我们如果想要它在每行的开头和结尾生效,我们需要用到多行修饰符 m。除此之外,还有 x、s、U、a、D、e等标志修正符。
标志 | 英文全称 | 描述 |
---|---|---|
x | extended | 忽略空白字符,可以多行书写,并使用#进行注释说明 |
s | single line | 单行模式,此模式下.能匹配任意字符,包括换行符 |
u | unicode | 模式字符串被当成UTF-8 |
U | Ungreedy | 使量词默认为非贪婪模式 |
A | Anchored | 锚点到模式的开始,或最近一次匹配的结束 |
J | Jchanged | 允许子模式重复命名,如:(?N1)(?N2) |
D | Dollar end only | $字符仅匹配目标字符串的结尾;没有此选项时,如果最后一个字符是换行符的话$字符也能匹配。 |
综上,零宽度断言用于查找一个位置,但不匹配该位置的内容,匹配断言之前的或之后的内容。
比如www.baidu.com这个域名。
匹配 www. 之后的内容,使用后发断言。
如图示:因为是零宽度,所以匹配到 www. 到 baidu.com 之间的位置。
此时,我们想得到后面的 baidu.com 只需要再加一个 (.*)
通配若干个任意字符即可。
注:后发断言不等于以 www. 开头,^
表示行首,^[w]{3}\.
表示以 www. 开头。
同理, .com 之前的内容,使用先行断言。
同理,因为是先行断言,需要在断言成功后,在前面进行匹配,可得到 www.baidu 。
注:后发断言不等于以 .com 结尾,$
表示行尾,\.com$
表示以 .com 结尾。
注意到,因为是零宽度的,因此先行断言和后发断言都不捕获文本 ,仅作为约束。也不会计算到结果分组内。
零宽度断言如下:
符号 | 描述 | 示例 | 匹配项举例 |
---|---|---|---|
?= | 正先行断言-存在 | (?=.com) |
baidu.com或google.com。匹配以.com结尾 |
?! | 负先行断言-排除 | (?!.net) |
baidu.com或baidu.cn。匹配以非.net结尾 |
?<= | 正后发断言-存在 | (?<=www) |
www.baidu.com。匹配以www开头 |
? | 负后发断言-排除 | (? | www.baidu.com。匹配以非www开头 |
正则表达式默认采用贪婪匹配模式。
因为存在 *
、+
、?
、{n,}
、{n,m}
等这类可以限定前一个匹配项次数的“量词”,且这些“量词”皆是虚指,如 *
表示零次或多次,+
表示一次或多次。
而默认使用贪婪模式会尽可能多的匹配。如:
“/a.*a/
” => greedy can be dangerous at times
可以使用 ? 将贪婪匹配模式转化为惰性匹配模式。
“/a.*a/
” => greedy can be dangerous at times
一览:贪婪模式加 “?” 转变为惰性模式
贪婪模式 | 解释 | 惰性模式 | 解释 |
---|---|---|---|
? | 重复0次或1次,取最大满足次数(最多1次)。 | ?? | 重复0次或1次,取最少满足次数(最少0次)。 |
+ | 重复1次或多次,取最大满足次数(不限次数)。 | +? | 重复1次或多次,取最少满足次数(最少1次)。 |
* | 重复任意次,取最大满足次数(不限次数)。 | *? | 重复任意次,取最少满足次数(最少0次)。 |
{n,m} | 重复n到m此,取最大满足次数(最少m次)。 | {n,m}? | 重复n到m此,取最少满足次数(最少n次)。 |
{n,} | 重复n次以上,取最大满足次数(不限次数)。 | {n,}? | 重复n次以上,取最少满足次数(最少n次)。 |
正则表达式主要依赖于元字符。 元字符不代表他们本身的字面意思,他们都有特殊的含义。一些元字符写在方括号中的时候有一些特殊的意思。以下是一些元字符的介绍:
元字符 | 描述 | 示例 |
---|---|---|
. | 句点匹配任意单个字符除了换行符。 | 1. f.o 匹配在字母“f”和“o”之间的任意一个字符;例如 fao、 f9o、 f#o 等2. .. 匹配任意两个字符3. .end 匹配在字符串 end 之前的任意一个字符 |
[ ] | 字符种类。匹配方括号内的任意字符。 | 1. b[aeiu]t bat、 bet、 bit、 but2. [ab][12] 一个包含2个字符的字符串,第一个字符是“a或“b”,然后是“1”或“2”,即可匹配项为 a1、a2、b1、b2 3. [0-9] 匹配0-9中任意一个数字 |
[^ ] | 否定的字符种类。匹配除了方括号里的任意字符 | 1. [^aeiou] 一个非元音字符,即除了aeiou 之外的任意字符2. [^\t\n] 不匹配制表符或者\n |
* | 匹配>=0个重复的在*号之前的字符。 | 1. b(an)* 匹配以b开头的an出现0次或多次的,如单词b,ban,banan2. [A-Za-z0-9]* 全文匹配 |
+ | 匹配>=1个重复的+号前的字符。 | 1. b(an)+ 匹配以b开头的an出现1次或多次的,如 ban, banan |
? | 标记?之前的字符为可选. | 1. b(an)? 匹配以b开头的an出现1次或0次的,如 b,ban |
{n,m} | 匹配num个大括号之前的字符或字符集 (n <= num <= m). | 1. a{3} 匹配3个连续的a组成的单词,即“aaa”2. b{2,3} 匹配b连续出现2到3次的单词,即“bb”或“bbb”3. c{2,} 匹配c连续出现2个以上的单词,即“c”,“cc”,“ccc”,“cccc”4. 注意,没有 c{,3} 这样的语法 |
(xyz) | 字符集,匹配与 xyz 完全相等的字符串. | 1. (abc) 匹配abc2. #(abc)? 匹配'#'后“abc”出现一次或0次,即“#abc”或“#” |
| | 或运算符,匹配符号前或后的字符. | 1. foo|bar 匹配 foo 或 bar |
\ | 转义字符,用于匹配一些保留的字符 [ ] ( ) { } . * + ? ^ $ \ | |
1. \(|\[|\{|\\\| 匹配“(”或“[”或“{”或“\”或“|” |
^ | 从开始行开始匹配. | 1. ^(T|t)he 匹配以 The 或 the 开头的字符串。2. ^(T|t)he.* 匹配以The 或 the 开头的整行 |
$ | 从末端开始匹配. | 1. end$ 匹配以end结尾的字符串 |
简写 | 描述 |
---|---|
. | 除换行符外的所有字符 |
\w | 匹配所有字母数字,等同于 [a-zA-Z0-9_] |
\W | 匹配所有非字母数字,即符号,等同于: [^\w] |
\d | 匹配数字: [0-9] |
\D | 匹配非数字: [^\d] |
\s | 匹配所有空格字符,等同于: [\t\n\f\r\p{Z}] |
\S | 匹配所有非空格字符: [^\s] |
\f | 匹配一个换页符 |
\n | 匹配一个换行符 |
\r | 匹配一个回车符 |
\t | 匹配一个制表符 |
\v | 匹配一个垂直制表符 |
\p | 匹配 CR/LF(等同于 \r\n ),用来匹配 DOS 行终止符 |
\b | 匹配任何单词边界( \B 与之相反)如\bThe\b |
\b\A(\Z) | 匹配字符串的起始(结束)( 另见上面介绍的^和$)注意区别: ^ 和 $ 分别代表一行(line)的开始和结束的位置; \A 和 \Z 分别代表输入(input)的开始和结束位置 |
格式 | 说明 | 示例 |
---|---|---|
(?iLmsux) | 在正则表达式中嵌入一个或者多个特殊“ 标记” 参数(或者通过函数/方法) | ( ?x),(?im) |
(?:…) | 表示一个匹配不用保存的分组 | (?:\w+\.)* |
(?P (? |
像一个仅由 name 标识而不是数字 ID 标识的正则分组匹配 | (?P) |
(?P=name) | 匹配先前命名的捕获组匹配的相同文本。 | (?P=data) |
(?#…) | 表示注释,所有内容都被忽略 | (?#comment) |
(?=…) | 匹配条件是如果…出现在之后的位置,而不使用输入字符串;称作正向前视断言 | (?=.com) |
(?!…) | 匹配条件是如果…不出现在之后的位置,而不使用输入字符串;称作负向前视断言 | (?!.net) |
(?<=…) | 匹配条件是如果…出现在之前的位置,而不使用输入字符串;称作正向后视断言 | (?<=800-) |
(? | 匹配条件是如果…不出现在之前的位置,而不使用输入字符串;称作负向后视断言 | (? |
(?(id/name)Y|N ) | 如果分组所提供的 id 或者 name(名称)存在,就返回正则表达式的条件匹配 Y 如果不存在,就返回 N; |N 是可选项 |
(?(1)y|x) |
(?>…) | 占用相应匹配内容,禁止随后的匹配项进行回溯匹配。非捕获组。 | |
(?|…) | 不允许为所有封闭的捕获组增加捕获组ID。 |
除此之外,还有递归、条件语句、内联、预定表达式等等…
扩展表示法,是以问号开始,形如(?…)。它们通常用于在判断匹配之前提供标记,实现一个前视(或者后视)匹配,或者条件检查。尽管圆括号使用这些符号,但是只有(?P)表述一个分组匹配。所有其他的都没有创建一个分组。
正则表达式模式 | 匹配的字符串 |
---|---|
(?:\w+.)* | 以句点作为结尾的字符串,例如“google.”、“twitter.”、“facebook.”,但是这些匹配不会保存下来供后续的使用和数据检索 |
(?#comment) | 此处并不做匹配,只是作为注释 |
(?=.com) | 如果一个字符串后面跟着“.com”才做匹配操作,并不使用任何目标字符串 |
(?!.net) | 如果一个字符串后面不是跟着“.net”才做匹配操作 |
(?<=800-) | 如果字符串之前为“800-”才做匹配,假定为电话号码,同样,并不使用任何输入字符串 |
(? | 如果一个字符串之前不是“192.168.”才做匹配操作,假定用于过滤掉一组 C 类 IP 地址 |
(?(1)y|x) | 如果一个匹配组 1(\1)存在, 就与 y 匹配; 否则,就与 x 匹配 |
正则中用 (
)
划分子表达式。目的是为了将其视为单一的实体来使用。
一般而言,在编程语言中分组id为0,表示匹配到的全部内容,分组id为1,表示匹配到的第一个子表达式的内容,以此类推。
使用 ..>
可以自定义分组名字,便于我们通过标签名取分组。下列以python为例:
每一个子表达式视为一个分组,在正则内部可以通过 $1、$2 引用,或者 \1 、\2。
在正则中,我们也可以使用 $+序号 表示分组,$1
表示第一个分组, ${foo}表示捕获被命名为foo的分组的字符串内容。
以JavaScript为例:使用$1、$2 提取分组内容。需要注意的是,不存在 $0
,如果想表示全部匹配项的话,使用 $&
表示。
示例:将匹配项替换为空字符串;将匹配项左右两侧加括号。
如果想在正则表达式之外使用这些,需要加上前缀 RegExp.$1 …
示例:
其他的,$`
表示捕获匹配项左侧文本内容,$'
表示捕获匹配项右侧文本内容。
不捕获分组
此外,如果分组标明为 (?:..)
则表示不捕获该分组。
示例:子表达式1不捕获后,分组1代指子表达式2捕获的内容。但是整体匹配项($&
)不受影响。
一览:
符号 | 说明 |
---|---|
$$ | 一个$符号 |
$1,$2… | 第1/2个分组捕获的匹配项 |
$& | 全部匹配项($1+$2…$n) |
&` | 匹配项前面的内容 |
&’ | 匹配项后面的内容 |
反向引用也基于分组的概念。规则为:由外向内,由左向右
形式为:\1
、\2
、… 分别表示引用第一个子表达式、第二子表达式…
与 $1 方式捕获不同的是,\1 方式捕获可用于正则模式串中。
匹配叠词
示例:可以用这种方式匹配叠词。
分析:
对于字符串“abcdeefghhhd”而言,如果我们想匹配叠词,我们应该怎么操作呢?
\w{2,} 不行,它只匹配到了两个字符。
而我们想要的是之前匹配到的字符再出现一次,因此我们自然想到子表达式。只需要再复用一次上一次子表达式匹配到的项即可。
此表达式,利用 \1 将第一个分组的匹配项引用到模式串中。
匹配过程如下:
aa
。很显然下一个字符是b,不匹配。bb
。不匹配ee
,下一个字符也是 e ,匹配成功。引用顺序
由外向内,自左向右。
回溯:内层括号匹配完之后,向上回溯。然后从第五组,e所在的括号开始。
正则教程:https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md
github 40k start的正则教程。
正则大全:https://any86.github.io/any-rule/
该网站收录了很多特殊正则表达式,拿来即用。
正则解析:https://jex.im/regulex
该网站可以分析正则表达式,以图解的形式拆分解析,便于理解。
正则练习:https://regexone.com/
该网站可以进行一些简单的正则练习,以刷题闯关的方式学习正则表达式。
正则工具:https://regex101.com/
该网站提供在线正则匹配,同时支持语法提示和代码生成,功能非常强大。