以下所有的验证都在
在线验证
1. 起始符 /
正则表达式的起始符
2. 限定符
+
匹配前面的子表达式**1次或多次
**。例如,zo+
能匹配 "zo"
以及"zoo"
,但不能匹配 "z"
。+
等价于 {1,}
。
?
匹配前面的子表达式**0次或1次
**。例如,do(es)?
可以匹配 "do"
、 "does"
、 "doxy"
中的 "do"
和 "does"
。
?
等价于 {0,1}
。
*
匹配前面的子表达式**0次或多次**
。例如,zo*
能匹配 "z"
以及"zoo"
。*
等价于 {0,}
。
. 句点符
匹配除换行符外 /r
和 /n
的所有字符,但一次只能匹配一个
{ }
{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?
。请注意在逗号和两个数之间不能有空格。
3. 普通字符
[ ]
所有的区间都会匹配一个结果返回
[ABC]
匹配包含在中括号中的所有字符,注意的是匹配的的字符不需要是连续的的,只要是在 [...]
中的字符就行,相当于字典。
[^ABC ]
和[ABC] 是取反的操作,表示不包含的匹配
区间操作 [A-Za-z0-0]
匹配某一区间的所有包含字符 例如匹配所有的中文[\u4e00-\u9fa5]
,这里是通过Unicode
4. 元字符
\d \D
配置所有的数字字符, 大写的表示取反 0-9
\w \W
匹配所有的 英文字母 + 数字 + 下划线
, 只能匹配一个,如果要匹配多个需要用到 \w+
\s \S
匹配任何空白字符
,包括空格、制表符、换页符
等等。
5. 逻辑运算符
与运算 (...)
括号内的做为一个整体匹配
或运算符 |
指明两项之间的一个选择。要匹配 |
,请使用 \|
A(ab|cd)D
两个匹配一个
6. 定位符
$
字符串结尾符
表示匹配的所有字符在句尾
^
首字符匹配
在中括号中[ ]
表示取反
\b
\B
边界匹配符
将两个空个之间的字符整体作为一个单词, 匹配边界包含某一特征的字符
7. 高级用法
贪婪匹配 or 懒惰匹配 ?
正则匹配的原则默认是按照贪婪匹配,表示尽可能多的匹配,也就是在满足条件的情况下,找到最长的。
<span> <div>this is very important!</div> </span>
我们要匹配所有的html标签 我们用 <.+>
,结果发现匹配的并不是 按照 <span>
和 <div>
而是把所有的都返回了,原因就是默认采用了贪婪匹配。
如果我们用<.+?>
表示我们用懒惰匹配,只要找到符合的就作为一个返回结果。
懒惰模式存在时对可匹配多个字符的操作符 例如
贪婪元字符 | 懒惰元字符 |
---|---|
+ | +? |
* | *? |
{} | {}? |
修饰符
/i
ignore - 不区分大小写 将匹配设置为不区分大小写,搜索时不区分大小写: A 和 a 没有区别。
/g
g global - 全局匹配 查找所有的匹配项。
/m
m multi line - 多行匹配 使边界字符 ^ 和 $ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾。
/s
特殊字符圆点. 中包含换行符 \n, 默认情况下的圆点 . 是匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后,
. 中包含换行符 \n。
回溯引用
回溯引用指的是模式的后半部分引用在前半部分中定义的子表达式,且只能用来引用模式里的子表达式()
子表达式即用元字符(
和)
括起来的部分)。简单理解,可以将回溯引用想象成对变量的引用。
使用
\1
表示引用第1个子表达式,\2
表示引用第2个子表达式,以此类推(通常,回溯引用从1
开始匹配)
注意
由于子表达式是按照其在表达式中的相对位置来引用的,因此有个不好之处在于,一旦改变了子表达式的相对位置,很容易引起正则的回溯引用失效。
例子:
我们要匹配一个HTML标签 <h1>-<h6>
中的内容,我们用这样的正则<[Hh][1-6]>.*?</[Hh][1-6]>
,这个可以匹配但是没有办法判断标签错误匹配的问题。
可以用回溯解决,主要时判断<h>
标签前面的数字是否匹配, <[hH]([1-6])>.*?</[hH]\1>
就可以解决。
替换操作符 $
$1
、$2
表达的是正则表达式中小括号(即分组)中的内容,$1
是第一个小括号(分组)中的匹配结果,$2
是第二个小括号(分组)中的匹配结果,以此类推。通常$1
、$2
用在替换操作中。如下:
前后查找
前后查找是查找具有某一条件的字符串
(正)向前查找 (?=)
如果我们想在一堆 URL 中拿到它们的协议名(scheme
)
http://www.test.com
https://www.example.com
ftp://ftp.aaa.com
我们可能会使用.+:
来完成要求,但是该模式匹配的是 http:,https:,ftp:
,要提取协议名我们还得对字符串做二次处理。所幸的是,使用向前查找.+(?=:)
就能够省去后面的冒号,其中子表达式(?=:)
表示找到:
就可以了,不把它包括在最终的匹配结果里。
(正)向后查找 (?<=)
除了?=
表示向前查找,还有很多正则表达式(JS不在其中。。。)也支持向后查找,操作符为 ?<=
。同样地,来看一个例子:对于如下文本
ABC01: $23.45
HGG43: $5.31
如果我们想将其中的价格匹配出来(不含$
),使用 [0-9.]+
是不行的,因为它也会匹配出 01
和 43
,这时候使用向后查找 (?<=\$)[0-9.]+
问题就迎刃而解了。
前后取非查找 (负向查找) (?!)
(?<!)
如果文本中我们只想匹配数量而不匹配金额:只匹配num
不匹配 $num
,比如下面这个例子
I paid $30 for 100 apples,
50 orange, and 60 pears,
I saved $5 on this order.
\b(?<!\$)\d+\b
最终的匹配的结果是只包含那些不以 $
开头的数值。
这个是所有操作符的总结
这时候可以取非
操作符 | 说明 |
---|---|
(?=) | 正向前查找 |
(?<=) | 正向前查找 |
(?!) | 负向前查找 |
(?<!) | 负向后查找 |
嵌入条件
北美的电话号码格式是 (123)456-7890
和 123-456-7890
,要匹配该模式,可能很容易就想到使用 \(?\d{3}\)?-?\d{3}-\d{4}
,但是该表达式也会匹配到非法的数据格式比如 (123-456-7890
,这种情况我们就需要使用条件:如果电话号码里有一个 (
,则第五个字符匹配 )
,否则匹配 -
。
嵌入条件的语法为:
(?(backreference)true-regex)
(?(backreference)true-regex|false-regex)
可以理解为:
if (backreference) { true-regex } else { false-regex }
分析这个模式,其中 (\()?
匹配一个可选的左括号,(?(1)\)|-)
是一个回溯引用条件,只有配对出现的括号才会被匹配。