正则表达式学习记录(一)——正则表达式的编写
文章目录
正则表达式的编写
交互式学习正则表达式:RegexOne 中文
正则表达式练习:RegExr
正则表达式文档:MDN Web Docs 正则表达式
基础篇
标记 |
说明 |
样例 |
|---|---|---|
| 直接匹配,输入什么匹配什么。 | RegEx: abcMatch: abcMatch: xyz abcdef |
|
. |
匹配任何单个字符。 | RegEx: .aMatch: 12 3abc |
\ |
转义字符,用于匹配某个用于标记的原始字符。 | RegEx: \.Match: Hi .Match: 3 .14 |
[] |
匹配特定范围内的单个字符 | RegEx: [abc]anMatch: bananaMatch: ab can |
[-] |
用简略的方式表示范围。例如 [2-6] 等价于 [23456] |
RegEx: [0-3][a-c]Match: 1a2b8y9z |
[^] |
排除特定范围内的单个字符 | RegEx: b[^e]rMatch: barber |
\d |
匹配 0-9 中的单个数字字符,相当于 [0-9] |
RegEx: \daMatch: 0 1a2b34 |
\D |
匹配单个非数字字符,相当于 [^0-9] |
RegEx: \D2Match: 1a a2b34 |
\s |
匹配单个空白字符,相当于 [\f\n\r\t\v\u0020\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]。其中, \f\n\r\t\v 与 ASCII 字符集中相同记号的转义字符同义,\uhhhh 为 Unicode 字符集对应字符的编号。 |
RegEx: \sMatch: Hello, world! |
\S |
匹配单个非空白字符,相当于 [^\f\n\r\t\v\u0020\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]。 |
RegEx: \SMatch: Hello, world! |
\w |
匹配单个单字字符,等价于 [A-Za-z0-9_]。 |
RegEx: \wMatch: 3.14 |
\W |
匹配单个非单字字符,等价于 [^A-Za-z0-9_] |
RegEx: \WMatch: 3 .14 |
\b |
表示单词边界,匹配一个单词的开始或结束,而不匹配任何实际字符。 | RegEx: \bword\bMatch: word and sword |
\B |
表示非单词边界,匹配字母或数字中间的位置,而不匹配任何实际字符。 | RegEx: \d\B\w\BMatch: 0 1ABMatch: A 4A2-g74t |
+ |
用于匹配 1 个或更多前面的标记。 | RegEx: a+b+Match: aaabb |
* |
用于匹配任意多个前面的标记,匹配的前面标记的数量可以为 0。 | RegEx: a+b*cMatch: aaabbbcccMatch: aaaccc |
? |
用于匹配前一个标记出现 0 次或 1 次。 | RegEx: apples?Match: appleMatch: appless |
{} |
用于匹配指定数量的前一个标记。 | RegEx: \d{2}Match: Jan 14, 2005 |
|
用于匹配指定数量范围的前一个标记,, 后可以为空。当 , 后留空时,则标识匹配前一个标记的最小值。 |
RegEx: \d{3,}Match: Jan 14, 2005 |
^ |
放在标记前,用于匹配开头的字符。 | RegEx: ^[Oo]n[Ee]Match: One by onE |
$ |
放在标记后,用于匹配末尾的字符。 | RegEx: [Oo]n[Ee]$Match: One by onE |
| |
或,| 前后的条件满足一个即可匹配 |
RegEx: I love dogs.Match: I love cats. |
进阶篇
- 捕获组
捕获组用 () 表示,括号中的内容为一组。在一个正则表达式中的捕获组,按照上括号 ( 的顺序进行编号,对于嵌套捕获组同样适用。例如在表达式 ((\d+) plus )\d+ 中,捕获组 ((\d+) plus ) 的编号为 1,而 \d+ 这一捕获组的编号为 2。
在正则表达式中,\ 后直接加一个数字 n 相当于“复制”了第 n 个捕获组,从而允许表达式匹配相同的内容。例如,对于表达式 (\w{3}) plus \1 就可以匹配 "one plus one","two plus two",但是无法匹配 "one plus two"。
如果不想让某个捕获组获得编号,可以在 ( 后加入 ?:,这样捕获组就会成为非捕获组,非捕获组不会获得编号。例如对于 "one plus one, two plus two" 这个字符串中除去 , 之外的内容,可以使用 ((\w{3}) plus \2) 匹配,也可以使用 (?:(\w{3}) plus \1) 匹配。
- 零宽断言
零宽断言有四种,分别是零宽正向先行断言 (?=)(指定后缀)、零宽正向后行断言 (?<=)(指定前缀)、零宽负向先行断言 (?!)(指定后缀不是)、零宽负向后行断言 (?<!)(指定前缀不是)。其中,被指定为或不为前缀或后缀的内容放在零宽断言中下括号 ) 前,先行断言置于标记后,后行断言置于标记前,且零宽断言只用于限定而不参与匹配。
例如我们想匹配 "hopefully seriously" 这两个单词中 "ly" 前的部分,即 "hopeful" 和 "serious",就可以使用零宽正向先行断言匹配后缀为 "ly" 的内容,因此我们使用表达式 \w+(?=ly) 进行匹配,并且 "ly" 并不会被匹配。如果我们想匹配 "Qty.: 100, Price: £150" 中数量 "Qty." 对应的值,则可使用 (?<!£)\d{3}
- 懒惰匹配
正则表达式默认遵循“贪婪匹配”原则,即尽可能匹配多的字符。例如使用表达式 a\w+c 匹配字符串 "abcabc" 时,会匹配整个字符串,而非单独某一段 "abc"。如果想让匹配尽量短,则可以使用 “懒惰匹配” 模式。懒惰匹配有如下几种模式:+?(出现至少一次,但是长度尽量短)、*?(出现任意次,但是长度尽量短)、??(至多出现一次,但是长度尽量短)、{,}?(出现指定次数,但是长度尽量短)。
例如对于字符串 "abcabc",若需要其匹配为两段 "abc",则可以使用表达式 a\w+?c。使用表达式 a\w{2,7}?c 可以匹配到 "abbbbcabbcabc" 的 "abbbc" 和 "abbc",而非将 "abbbcabbc" 作为一个整体匹配。
另外需要注意的是,正则表达式从字符串的开头开始匹配,使用懒惰匹配只会改变匹配到的结尾的位置,而非开头的位置。例如使用 a\w*?c 匹配字符串 "aaaccc" 会得到 "aaac" 而非 "ac"。
- 标志位
到目前为止,本文中出现的所有正则表达式都未使用标志位,而前文中所有的表达式都是默认使用 /g 作为标志位得到的相应的结果。正则表达式中有如下常见标志位:g(global,全局匹配)、i(case intensitive,不区分大小写)、m(multiline,多行匹配)、s(single line,单行匹配)。
对于上面的正则表达式 a\w*?c,其完整的写法是 /a\w*?c/g。例如在匹配 "jack_gdn JackGDN JGDN" 这几个单词时,一个完整的正则表达式是 /j.*?gdn/gi。s 标志位会将多行内容看作一行内容,并且去除 \n 或 \r\n。m 标志位对于 ^ 和 $ 标记格外有用。例如对于一段文本:
1jack_gdn
2JackGDN
3JGDN
如果使用 /^j.*?gdn/gi 匹配,则只会匹配到第一行的 "jack_gdn",而如果使用 /^j.*?gdn/gim 匹配,则会将三行内容全部匹配上。
测试正则表达式
如果这一部分显示有问题,请把 URL 中的查询(?query= 及后面的部分)全部删除