0%

正则表达式语法笔记及常用表达式

对于正则表达式一向了解不多,假期期间随着《正则表达式必知必会》快速学习了一下正则表达式的基本使用,在此记录一下。

正则表达式语法笔记

常用元字符

元字符 作用
. 换行符外任意字符
\d 一个数字,等价于 [0-9]
\D 一个非数字,等价于 [^0-9]
\w 一个数字、字符及下划线,等价于[a-zA-Z0-9_](最后一个是下划线_)
\W 一个非数字、字符和下划线,等价于[^a-zA-Z0-9_](最后一个是下划线_),注意,[]内的 ^,对之后每个组合都取非,不只是紧接的
\s 一个空白字符,等价于[\f\n\r\t\v ](最后有个空格),换页、换行、回车、制表、垂直制表符、空格
\S 一个非空白字符,等价于[^\f\n\r\t\v ](最后有个空格)

要注意,[]内出现的的元字符对应字符,不按照元字符处理,不需要要转义,如“.”、“$”等

重复匹配

表达式 作用
+,[]+ 匹配前面字符/集合的一次或多次,贪婪
*,[]* 匹配前面字符/集合的零次或多次,贪婪
?,[]? 匹配前面字符/集合的零次或一次,等价于{0,1}
+? +的懒惰情况
*? *的懒惰情况
{n},[]{n} 字符或集合出现 n 次
{n,m},[]{n,m} 字符或集合出现 n 到 m 次
{n,},[]{n,} 字符或集合出现 n 到无穷次/至少 n 次,贪婪
{n,}?,[]{n,}? {n,},[]{n,}的懒惰情况

关于贪婪和懒惰,可见例子:

1
<B>AK</B> and <B>HI</B>

使用

1
<B>.*</B>

将匹配到

1
<B>AK</B> and <B>HI</B>

而懒惰形式

1
<B>.*?</B>

将匹配到

1
<B>AK</B>

1
<B>HI</B>

边界

表达式 作用
\b 单词边界,相当于 \w 和 \W 之间的位置
\B 非单词边界,即 字母数字下划线之间 或 非字母数字下划线之间
^ 匹配字符串开头
$ 匹配字符串结尾
(?m) 加在最前,使 ^ 和 $ 匹配行内字符串开头和行内字符串结尾。ps:不一定每种语法都适用
\A 同 ^,但 (?m) 对其无效
\Z 同 $,但 (?m) 对其无效

回溯引用

表达式 作用
() 括号内的作为一个子表达式,其中的元字符对应字符要匹配时需要转义,如”.”
\1 \1、\2 等是回溯引用,\1 将回溯引用第一个子表达式,\2 回溯第二个,以此类推(\0 在多种语法中表示整个正则表达式)

例如,使用回溯引用

1
<[Hh]([1-6])>.*?</[Hh]\1>

来匹配 html 1 到 6 级标题。

另外注意,使用

1
.*?

而不是

1
.*

是为了避免过度匹配,比如,使用

1
<[Hh]([1-6])>.*</[Hh]\1>

将在

1
<h1>test1</h1><h2>test2</h1>

中匹配到

1
<h1>test1</h1><h2>test2</h1>

前后查找

表达式 作用
?= 向前查找,要作为子表达式使用
?<= 向后查找,要作为子表达式使用
?! 负向前查找,要作为子表达式使用
?<! 负向后查找,要作为子表达式使用

例如,对于

1
2
http://matian.connorma.cn
https://matian.connorma.cn

使用向前匹配

1
\w+(?=:)

的匹配结果为

1
2
http
https

使用向后匹配

1
(?<=://).*

的匹配结果为

1
2
matian.connorma.cn
matian.connorma.cn

向前查找和向后查找可以起来,比如对上例,

1
(?<=://)[\w\.]*(?=\.cn)

将匹配到

1
2
matian.connorma
matian.connorma

对于负向前/后查找,比如,

1
2
3
4
30
200
$59
45

若要匹配所有金额数值,可以使用

1
(?<=\$)\d+

将匹配到

1
59

若要匹配所有非金额的数字,可以使用

1
\b(?<!\$)\d+\b

将匹配到

1
2
3
30
200
45

这里要注意,如果不使用 \b,而使用如下的表达式

1
(?<!\$)\d+

匹配结将是

1
2
3
4
30
200
9
45

条件(或)

对 OR 运算符“|”,

使用时注意

  1. 有优先级问题,如 19|20\d{2},匹配 19,或者 20xx 的四位数字;(19|20)\d{2},匹配 19xx 或者 20xx 的四位数字。

  2. 表现出短路,如 (((\d{1,2})|(1\d\d)|(2[0-4]\d)|(25[0-5])).){3}((\d{1,2})|(1\d\d)|(2[0-4]\d)|(25[0-5])) 意在匹配 ip 地址,但是好像,经测试,| 在正则表达式中,也表现出了短路的特性,会导致最后一段出现类似 255 只匹配到 25 的情况,而最后一段出现 256 时,将匹配到 25。\b(((\d{1,2})|(1\d\d)|(2[0-4]\d)|(25[0-5])).){3}((\d{1,2})|(1\d\d)|(2[0-4]\d)|(25[0-5]))\b 看起来更合理。

其他嵌入条件暂时没看。

常用表达式

  1. 匹配空白行(linux + windows)

    1
    [\r]?\n[\s]\*[\r]?\n
  2. 匹配 Email

    1
    (\w+\.)*\w*@(\w+\.)+[A-Za-z]+
  3. 匹配 URL 地址

    1
    [a-zA-z]+://[^\s]*
  4. 匹配 ip 地址

    1
    ((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))