• 菜鸟教程 https://m.runoob.com/regexp/regexp-syntax.html
  • 正则表达式在线测试 https://c.runoob.com/front-end/854/
  • 基础篇 https://blog.csdn.net/lxcnn/article/details/4304651
  • 正则工具 https://jex.im/regulex/#!flags=&re=%5E(a%7Cb)*%3F%24*%3F%24)

    语法参考

    | 字符 | 描述 | | —- | —- | | . | 匹配除换行符(\n、\r)之外的任何单个字符 要匹配 . ,请使用 \. | | ^ | 匹配输入字符串的开始位置 | | $ | 匹配输入字符串的结束位置 | | \d,\w,\s | 匹配数字、字符、空格 | | \D,\W,\S | 匹配非数字、非字符、非空格 | | [abc] | 匹配 a、b 或 c 中的一个字母 | | [a-z] | 匹配 a 到 z 中的一个字母 | | [^abc] | 匹配除了 a、b 或 c 中的其他字母 | | aa | bb | | ? | 0 次或 1 次匹配 相当于 {0,1} | | | 匹配 0 次或多次 相当于 {0,} | | + | 匹配 1 次或多次 相当于 {1,} | | {n} | 匹配 n次
    n 是一个非负整数。匹配确定的 n 次。例如,o{2} 不能匹配 “Bob” 中的 o,但是能匹配 “food” 中的两个 o。 | | {n,} | 匹配 n次以上
    n 是一个非负整数。至少匹配n 次。例如,o{2,} 不能匹配 “Bob” 中的 o,但能匹配 “foooood” 中的所有 o。o{1,} 等价于 o+。o{0,} 则等价于 o
    。 | | {m,n} | 最少 m 次,最多 n 次匹配
    m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。例如,o{1,3} 将匹配 “fooooood” 中的前三个 o。o{0,1} 等价于 o?。请注意在逗号和两个数之间不能有空格。 |
量词 描述
n+ 匹配任何包含至少一个 n 的字符串。
例如,/a+/ 匹配 “candy” 中的 “a”,”caaaaaaandy” 中所有的 “a”。
n* 匹配任何包含零个或多个 n 的字符串。
例如,/bo*/ 匹配 “A ghost booooed” 中的 “boooo”,”A bird warbled” 中的 “b”,但是不匹配 “A goat grunted”。
n? 匹配任何包含零个或一个 n 的字符串。
例如,/e?le?/ 匹配 “angel” 中的 “el”,”angle” 中的 “le”。
n{X} 匹配包含 X 个 n 的序列的字符串。
例如,/a{2}/ 不匹配 “candy,” 中的 “a”,但是匹配 “caandy,” 中的两个 “a”,且匹配 “caaandy.” 中的前两个 “a”。
n{X,} X 是一个正整数。前面的模式 n 连续出现至少 X 次时匹配。
例如,/a{2,}/ 不匹配 “candy” 中的 “a”,但是匹配 “caandy” 和 “caaaaaaandy.” 中所有的 “a”。
n{X,Y} X 和 Y 为正整数。前面的模式 n 连续出现至少 X 次,至多 Y 次时匹配。
例如,/a{1,3}/ 不匹配 “cndy”,匹配 “candy,” 中的 “a”,”caandy,” 中的两个 “a”,匹配 “caaaaaaandy” 中的前面三个 “a”。注意,当匹配 “caaaaaaandy” 时,即使原始字符串拥有更多的 “a”,匹配项也是 “aaa”。
n$ 匹配任何结尾为 n 的字符串。
^n 匹配任何开头为 n 的字符串。
?=n 匹配任何其后紧接指定字符串 n 的字符串。
?!n 匹配任何其后没有紧接指定字符串 n 的字符串。

正则表达式 - 元字符

  • 下表包含了元字符的完整列表以及它们在正则表达式上下文中的行为: | 字符 | 描述 | | —- | —- | | \ | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,’n’ 匹配字符 “n”。’\n’ 匹配一个换行符。序列 ‘\‘ 匹配 “” 而 “(“ 则匹配 “(“。 | | ^ | 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置。 | | $ | 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前的位置。 | | | 匹配前面的子表达式零次或多次。例如,zo 能匹配 “z” 以及 “zoo”。 等价于{0,}。 | | + | 匹配前面的子表达式一次或多次。例如,’zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。 | | ? | 匹配前面的子表达式零次或一次。例如,”do(es)?” 可以匹配 “do” 或 “does” 。? 等价于 {0,1}。 | | {n} | n 是一个非负整数。匹配确定的 n 次。例如,’o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。 | | {n,} | n 是一个非负整数。至少匹配n 次。例如,’o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。’o{1,}’ 等价于 ‘o+’。’o{0,}’ 则等价于 ‘o’。 | | {n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,”o{1,3}” 将匹配 “fooooood” 中的前三个 o。’o{0,1}’ 等价于 ‘o?’。请注意在逗号和两个数之间不能有空格。 | | ? | 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 “oooo”,’o+?’ 将匹配单个 “o”,而 ‘o+’ 将匹配所有 ‘o’。 | | . | 匹配除换行符(\n、\r)之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用像”(. | | x|y | 匹配 x 或 y。例如,’z|food’ 能匹配 “z” 或 “food”。’(z|f)ood’ 则匹配 “zood” 或 “food”。 | | [xyz] | 字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。 | | [^xyz] | 负值字符集合。匹配未包含的任意字符。例如, ‘[^abc]’ 可以匹配 “plain” 中的’p’、’l’、’i’、’n’。 | | [a-z] | 字符范围。匹配指定范围内的任意字符。例如,’[a-z]’ 可以匹配 ‘a’ 到 ‘z’ 范围内的任意小写字母字符。 | | [^a-z] | 负值字符范围。匹配任何不在指定范围内的任意字符。例如,’[^a-z]’ 可以匹配任何不在 ‘a’ 到 ‘z’ 范围内的任意字符。 | | \b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配”never” 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。 | | \B | 匹配非单词边界。’er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。 | | \cx | 匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c’ 字符。 | | \d | 匹配一个数字字符。等价于 [0-9]。 | | \D | 匹配一个非数字字符。等价于 [^0-9]。 | | \f | 匹配一个换页符。等价于 \x0c 和 \cL。 | | \n | 匹配一个换行符。等价于 \x0a 和 \cJ。 | | \r | 匹配一个回车符。等价于 \x0d 和 \cM。 | | \s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 | | \S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 | | \t | 匹配一个制表符。等价于 \x09 和 \cI。 | | \v | 匹配一个垂直制表符。等价于 \x0b 和 \cK | | \w | 匹配字母、数字、下划线。等价于’[A-Za-z0-9]’。 | | \W | 匹配非字母、数字、下划线。等价于 ‘[^A-Za-z0-9]’。 |

正则表达式的先行断言(lookahead)和后行断言

正则表达式的先行断言(lookahead)和后行断言(lookbehind)
参考链接——正则表达式中?=和?:和?!的理解

(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 ‘\(‘ 或 ‘\)’。
(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 “或” 字符 (|) 来组合一个模式的各个部分是很有用。例如, ‘industr(?:y|ies) 就是一个比 ‘industry|industries’ 更简略的表达式。
(?=pattern) 正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,”Windows(?=95|98|NT|2000)”能匹配”Windows2000”中的”Windows”,但不能匹配”Windows3.1”中的”Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如”Windows(?!95|98|NT|2000)”能匹配”Windows3.1”中的”Windows”,但不能匹配”Windows2000”中的”Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?<=pattern) 反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,”(?<=95|98|NT|2000)Windows”能匹配”2000Windows”中的”Windows”,但不能匹配”3.1Windows”中的”Windows”。
(?<!pattern) 反向否定预查,与正向否定预查类似,只是方向相反。例如”(?<!95|98|NT|2000)Windows”能匹配”3.1Windows”中的”Windows”,但不能匹配”2000Windows”中的”Windows”。

先行断言和后行断言详解

  • 我们知道,正则表达式中大部分的结构所匹配的文本最终会出现在匹配结果中,但也有一部分结构并不真正匹配文本,而只是负责判断某个位置左/右侧是否符合要求,这种结构被称为断言
  • 常用的断言有以下四种 ?=、?<=、?!、?<! :::info exp1(?=exp2):查找 exp2 前面的 exp1。 ::: :::info (?<=exp2)exp1:查找 exp2 后面的 exp1。 ::: :::info exp1(?!exp2):查找后面不是 exp2 的 exp1。 ::: :::info (?<!exp2)exp1:查找前面不是 exp2 的 exp1。 ::: ``` “中国人”.replace(/(?<=中国)人/, “rr”) // 匹配中国人中的人,将其替换为rr,结果为 中国rr “法国人”.replace(/(?<=中国)人/, “rr”) // 结果为 法国人,因为人前面不是中国,所以无法匹配到

()表示捕获分组,()会把每个分组里的匹配的值保存起来,使用$n(n是一个数字,表示第n个捕获组的内容) (?:)表示非捕获分组,和捕获分组唯一的区别在于,非捕获分组匹配的值不会保存起来

  1. ---
  2. - ?=pattern和?<=pattern 分别表示匹配断言成立时左侧和右侧的文本,只有断言成立了,左侧或右侧的文本才会被匹配,但断言所匹配的结果并不会出现在匹配结果中,具体例子可以看以下代码
  3. ```javascript
  4. var testReg=/test(?=123)/;
  5. var result=testReg.exec('test123');
  6. console.log(result[0])//输出test
  7. var result2=testReg.exec('test12');
  8. console.log(result2)//输出null
  • 我们可以看到test(?=123)可以匹配到test123中的test,但是并不能匹配test12中的test,对于?<=pattern同理,可以看以下代码 ```javascript var testReg=/(?<=123)test/; var result=testReg.exec(‘123test’); console.log(result[0])//输出test

var result2=testReg.exec(‘12test’); console.log(result2)//输出null

  1. - 同样(?=123)test可以匹配到123test中的test,匹配不到12test中的test,并且匹配结果同样不包含断言
  2. - 对于?!pattern和?<!pattern可以看成是上面两个表达式的取反,分别匹配断言不成立时的左侧和右侧文本,具体可以看以下代码
  3. ```javascript
  4. var testReg=/test(?!123)/;
  5. var result=testReg.exec('test123');
  6. console.log(result)//输出null
  7. var result2=testReg.exec('test12');
  8. console.log(result[0])//输出test
  1. var testReg=/(?<!123)test/;
  2. var result=testReg.exec('123test');
  3. console.log(result)//输出null
  4. var result2=testReg.exec('12test');
  5. console.log(result2[0])//输出test
  • 如上我们可以看到这个时候要匹配到左侧或者右侧的test,需要括号里的断言不成立时,才能匹配的到了

参考文章

正则表达式特殊字符

这两个 ^…$ 放在一起常常被用于测试一个字符串是否完全匹配一个模式

特别字符 描述
$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n’ 或 ‘\r’。要匹配 $ 字符本身,请使用 \$。
( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
* 匹配前面的子表达式零次或多次。要匹配 字符,请使用 \
匹配前面的子表达式零次或多次。例如,zo 能匹配 “z” 以及 “zoo” 等价于 {0,}。
+ 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。
匹配前面的子表达式一次或多次。例如,zo+ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。
. 匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。
[ 标记一个中括号表达式的开始。要匹配 [,请使用 \[。
? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。
匹配前面的子表达式零次或一次。例如,do(es)? 可以匹配 “do”“does”“doxy” 中的 “do” 。? 等价于 {0,1}。
\ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, ‘n’ 匹配字符 ‘n’。’\n’ 匹配换行符。序列 ‘\\‘ 匹配 “\“,而 ‘\(‘ 则匹配 “(“。
^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合。要匹配 ^ 字符本身,请使用 \^。
{ 标记限定符表达式的开始。要匹配 {,请使用 \{。
| 指明两项之间的一个选择。要匹配 |,请使用 \|。

正则表达式中的 [ ] 与 ( )

  • () 的内容表示一个子表达式,() 本身不匹配任何字符,也不限制匹配任何字符,只是把括号内的内容作为同一个表达式来处理

    • 例 (ab){1,3}:表示 ab 一起连续出现 最少 1 次,最多 3 次
  • [] 表示匹配的字符在 [] 中,并且只能出现一次,并且特殊字符写在 [] 会被当成普通字符来匹配

    • 例 [(a)]:匹配 ( 、 a 、 )这三个字符

1 圆括号 ()
  • 圆括号在正则表达式中表示的概念,主要应用于限制多选结构的范围、分组、捕获文本、环视。

    1.1 示例:多选结构
  • ( a|b|c ):匹配 a 或 b1 或 c

    1.2 示例:分组
  • (abc)?:匹配 abc 一次或者零次

    1.3 示例:捕获文本
  • (aaa)(bbb)(ccc)(?:ddd)(eee):可以用 $1 获取 (aaa) 匹配到的内容,用 $3 则获取到了 (ccc) 匹配到的内容,而 $4 则获取的是由 (eee) 匹配到的内容

    1.4 示例:环视
  • a(?=bbbbb):顺序环视,表示 a 后面必须紧跟 5 个连续的 b

    2 方括号 []
  • 方括号在正则表达式中用于单个匹配,可用于字符集、排除字符集之中。

    2.1 示例:字符集
  • [0-9]:表示此位置上的字符只能展示 0 到 9 这十个数字的其中一个

image.png

2.2 示例:排除字符集
  • [^0-3]:表示此位置上的字符不可以是 0 到 3

    定位符

  • 定位符使您能够将正则表达式固定到行首或行尾。它们还使您能够创建这样的正则表达式,这些正则表达式出现在一个单词内、在一个单词的开头或者一个单词的结尾。

  • 定位符用来描述字符串或单词的边界,^ 和 $ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。 | 字符 | 描述 | | —- | —- | | ^ | 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与 \n 或 \r 之后的位置匹配。 | | $ | 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与 \n 或 \r 之前的位置匹配。 | | \b | 匹配一个单词边界,即字与空格间的位置。 | | \B | 非单词边界匹配。 |

运算符

运算符 描述
\ 转义符
(), (?:), (?=), [] 圆括号和方括号
*, +, ?, {n}, {n,}, {n,m} 限定符
^, $, \任何元字符、任何字符 定位点和序列(即:位置和顺序)
| 替换,”或”操作
字符具有高于替换运算符的优先级,使得”m|food”匹配”m”或”food”。若要匹配”mood”或”food”,请使用括号创建子表达式,从而产生”(m|f)ood”。

贪婪模式

  • 在贪婪模式默认情况下,像 * 和 + 这样的量词是贪婪的,正则表达式引擎会尝试尽可能多地重复量词,匹配尽可能多的字符串
  • 当不可能检测更多时,然后它再匹配模式的剩余部分
  • 如果没有匹配,则减少重复的次数(回溯),并再次尝试

    懒惰模式

  • 懒惰模式只能够通过带 ? 的量词启用,在每次重复量词之前,引擎会尝试去匹配模式的剩余部分 | 符号 | 说明 | | —- | —- | | *? | 重复任意次,但尽可能少重复 | | +? | 重复1次或更多次,但尽可能少重复 | | ?? | 重复0次或1次,但尽可能少重复 | | {n,m}? | 重复n到m次,但尽可能少重复 | | {n,}? | 重复n次以上,但尽可能少重复 |

  • ? 量词后面的字符使量词非贪婪,意思是它一旦找到匹配就会停止

  • x*?、x+?、x??、x{n}?、x{n,}、x{n,m}

    边界断言

  • 对于文本、词或模式,边界可以用来表明它们的起始或终止部分,向前断言,向后断言以及条件表达式 | 字符 | 描述 | | —- | —- | | ^ | 匹配输入的开头 | | $ | 匹配输入的结束 | | \b | 匹配一个单词的边界 | | \B | 匹配非单词边界 |

正则表达式中问号(?)的用法详解

  • 正则表达式中“?”的用法大概有以下几种

    1 直接跟随在子表达式后面

    这种方式是最常用的用法,具体表示匹配前面的一次或者0次,类似于{0,1},如:abc(d)?可匹配abc和abcd

2 非贪婪匹配(懒惰模式)

关于贪婪和非贪婪,贪婪匹配的意思是,在同一个匹配项中,尽量匹配更多所搜索的字符,非贪婪则相反。正则匹配的默认模式是贪婪模式,当?号跟在如下限制符后面时,使用非贪婪模式(*,+,?,{n},{n,},{n,m})

如正则表达式 \S+c 匹配字符串aaaacaaaaaaac的结果是aaaacaaaaaaac,而\S+?c则会优先匹配aaaac

非获取匹配

当我们使用正则表达式的时候,捕获的字符串会被缓存起来以供后续使用,具体表现为每个()中的表达式所匹配到的内容在进行正则匹配的过程中,都会被缓存下来,如以下代码

  • RegExp.$1是RegExp的一个属性,指的是与正则表达式匹配的第一个 子匹配(以括号为标志)字符串,以此类推,RegExp.$2,RegExp.$3,..RegExp.$99总共可以有99个匹配
    1. var testReg=/(a+)(b*)c/;
    2. testReg.test('aaaabbbc');//输出true
    3. console.log(RegExp.$1);//输出aaaa
    4. console.log(RegExp.$2);//输出bbb
    但是,如果在子分组中加入?:之后,分组依然成立,但是不会被缓存下来,看以下代码
    1. var testReg=/(a+)(?:b*)c/;
    2. testReg.test('aaaabbbc');//输出true
    3. console.log(RegExp.$1);//输出aaaa
    4. console.log(RegExp.$2);//输出""

    正则表达式与字符串方法

    | 方法 | 描述 | | —- | —- | | exec | 一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回 null) | | test | 一个在字符串中测试是否匹配的RegExp方法,它返回 true 或 false | | match | 一个在字符串中执行查找匹配的String方法,它返回一个数组,在未匹配到时会返回 null | | matchAll | 一个在字符串中执行查找所有匹配的String方法,它返回一个迭代器(iterator) | | search | 一个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1 | | replace | 一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串 | | split | 一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的 String 方法 |

正则案例

1.邮箱

正则表达式 - 图2

2. 55 ^\d+\?\d+$

image.png

  • ^ 匹配输入字符串开始的位置
  • \d+ 表示1个或多个0到9的数字( +匹配 1 次或多次)
  • *? *将特殊字符*转换为字符标记 (匹配前面的子表达式零次或一次)
  • $ 匹配输入字符串结尾的位置

    js 字符串中只保留数字replace()

  • 语法 stringObject.replace(regexp/substr,replacement) | 参数 | 描述 | | —- | —- | | regexp/substr | 必需。规定子字符串或要替换的模式的 RegExp 对象。
    请注意,如果该值是一个字符串,则将它作为要检索的直接量文本模式,而不是首先被转换为 RegExp 对象。 | | replacement | 必需。一个字符串值。规定了替换文本或生成替换文本的函数。 |

  1. let str = "dd123f";
  2. let numStr = str.replace(/[^0-9]/ig, "");
  3. console.log(numStr); // "123"