正则表达式-常用构造子列表

扶醉桌前 提交于 2020-02-29 10:34:27

字符

    表示单个字符。例如a,它将匹配字符串中第一次出现的字符a;它也可以匹配第二个 a,这必须是你告诉正则表达式引擎从第一次匹配的地方开始搜索。

    可以使用特殊字符序列代表某些不可显示字符。

构造 匹配
B 字符B
\xhh 十六进制值为oxhh的字符
\uhhhh 十六进制值为oxhhhh的Unicode字符
\t 制表符Tab:(‘\u0009’) 
\r 回车符:(‘\u000D’)
\n 换行符:(‘\u000A’)
\f 换页符:(‘\u000C’)
\e 转义符(Escape):(‘\u001B’)

字符集

    字符集是由一对括号[]括起来的字符集合。使用字符集,可以告诉正则表达式引擎仅仅匹配多个字符中的一个。

    字符集可以出现在其它字符集中,并且可以包含并集运算符(隐式)和交集运算符 (&&)。

构造 匹配
[abc] a、b或c(等效于a|b|c)
[^abc] 除了a、b或c的任何字符(否定)
[a-zA-Z] a到z或A到Z的任何字符(范围)
[abc[hij]] a、b、c、h、i或j,等效于a|b|c|h|i|j(并集)
[a-z&&[hij]] h、i或j(交集)


    并集和交集的应用示例如下:

    [a-c[h-j]]

    a到c或h到j的任何字符(并)

    [a-z&&[^hij]]

    a到z,除了h、i、j(减去),等效于[a-gk-z]

    [a-z&&[^h-j]]

    a到z,而非h到j(减去),等效于[a-gk-z]


预定义字符集

    预定义字符集可以用在方括号之内或之外。

    例如\s\d匹配一个空白符后面紧跟一个数字;[\s\d]匹配单个空白符或数字。

构造 匹配
\d 数字:[0-9]
\D 非数字:[^0-9]
\s 空白字符:空格、制表、回车、换行、换页
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]

边界匹配符

构造 匹配
^ 输入序列的开始
当启用多行模式后,还可以匹配行的开始
$ 输入序列的结尾
当启用多行模式后,还可以匹配行的结尾
\b 单词边界
  • \b匹配的是位置,这种匹配是0长度的

  • \b匹配一个“字母数字下划线”序列的开始和结束位置,在开始位置前面的字符或结束位置后面的字符不能是字母、数字或下划线

\B 非单词边界:[^\b]
\B匹配的位置是两个“单词字符”之间或两个“非单词字符”之间的位置
\G 上一个匹配的结尾

逻辑操作符

构造 匹配
XY X后跟Y
X|Y X或Y
匹配分支条件时,将会从左到右地测试每个条件,如果满足了某个分支的话,就不会去再管其它的条件了。例如\d{5}|\d{5}-\d{4},只会匹配5位数字以及9位数字的前5位
(X) 捕获组(capturing group)。可以在表达式中用\i引用第i个捕获组

量词

    量词描述了一个模式吸收输入文本的模式。

  • 贪婪型:量词总是贪婪的,除非有其它的选项被设置。贪婪表达式会为所有可能的模式发现尽可能多的匹配。

  • 懒惰型:懒惰型表达式匹配满足模式所需的最少字符数。

  • 占有型:目前,占有型量词只在Java语言中可用。当正则表达式被应用于字符串时,它会产生相当多的状态,以便在匹配失败时可以回溯。而占有型量词并不保存这些中间状态,因此它可以防止回溯。它们常常用来防止正则表达式失控,因此可以使正则表达式执行起来更有效。

贪婪型 懒惰型 占有型 如何匹配
X? X?? X?+ 0次或1次X(等效于X{0,1})
事实上表示前导字符是可选的
X* X*? X*+ 0次或多次X(等效于X{0,} )
事实上表示前导字符可以出现任意次数
X+ X+? X++ 1次或多次X(等效于X{1,} )
事实上表示前导字符至少重现1次
X{n} X{n}? X{n}+ 恰好n次X
X{n,} X{n,}? X{n,}+ 至少n次X
X{n,m} X{n,m}? X{n,m}+ X至少n次,且不超过m次


    量词的贪婪性

    量词?+*会导致正则表达式引擎尽可能的重复前导字符。只有当这种重复会引起整个正则表达式匹配失败的情况下,引擎会进行回溯。也就是说,它会放弃最后一次的“重复”,然后处理正则表达式余下的部分。

    例如,用一个正则表达式匹配一个HTML标签。

    输入字符串为”This is a <EM>first</EM> test”,正则表达式<.+>返回”<EM>first</EM>”。这是因为+是贪婪性的。

    让我们来看看正则引擎的处理过程。

    正则表达式的第一个符号是“<”,这是一个字符;第二个符号是“.”,匹配了字符“E”;第三个符号是“+”,它可以一直可以匹配后面的字符,直到一行的结束;然后遇到了换行符,匹配失败(“.”不匹配换行符)。于是引擎开始对下一个正则表达式符号进行匹配,也即试图匹配“>”。到目前为止,正则表达式“<.+”已经匹配了“<EM>first</EM> test”。引擎会试图将“>”与换行符进行匹配,结果失败了。于是引擎进行回溯,“<.+”匹配“<EM>first</EM> tes”,于是引擎将“>”与“t”进行匹配,显然还是会失败。这个过程继续,直到“<.+”匹配“<EM>first</EM”,“>”与“>”匹配。最后引擎找到了一个匹配的部分“<EM>first</EM>”。

    因为正则导向的引擎是“急切的”,所以它会急着报告它找到的第一个匹配。而不是继续回溯,即使可能会有更好的匹配,例如“<EM>”。所以由于“+”的贪婪性,使得引擎返回了一个最长的匹配。


    可以使用下列方式来解决量词的贪婪性带来的问题。

  • 用懒惰性取代贪婪性。

    输入字符串为”This is a <EM>first</EM> test”,正则表达式<.+?>返回”<EM>”。

    让我们再来看看正则引擎的处理过程。

    正则表达式符号“<”会匹配素如字符串的第一个“<”。下一个正则符号是“.”。这次是一个懒惰的“+?”来重复上一个字符,它会尽可能少的重复上一个字符。因此引擎匹配“.”和字符“E”,然后用“>”匹配“M”,结果失败了。引擎会进行回溯,和上一个例子不同,因为是惰性重复,所以引擎是扩展惰性重复而不是减少;于是“<.+”现在被扩展为“<EM”。引擎继续匹配下一个符号“>”。这次得到了一个成功匹配。引擎于是报告“<EM>”是一个成功的匹配。

  • 惰性扩展的一个替代方案。

    输入字符串为”This is a <EM>first</EM> test”,正则表达式<[^>]+>返回”<EM>”。

    这是一个更好的替代方案。可以用一个贪婪重复与一个取反字符集<[^>]+>。之所以说这是一个更好的方案在于使用惰性重复时,引擎会在找到一个成功匹配前对每一个字符进行回溯。而使用取反字符集则不需要进行回溯。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!