正则表达式
regular expression(regex)
匹配纯文本 Ben Forta
匹配任何一个除了换行符以外的单个字符 .
匹配特殊字符 \ (元字符)
匹配元字符 \\
匹配多个字符中的某一个 [ ]
元字符[和]来定义一个字符集合,它们本身不匹配任何字符;
在不需要区分大小写或者是只须匹配某个特定部分的搜索操作里比较常见;
字符集合区间-
A ~ Z / a ~ z / 0 ~ 9
字符区间的首、尾字符可以是ASCII字符表里的任意字符。但在实际工作中,最常用的字符区间还是数字字符区间和字母字符区间。
避免区间的尾字符小于它的首字符,这种区间没有意义,而且往往会让整个模式失效
- 是一个特殊的元字符,它只能用在[和]之间。在字符集合以外的地方,只是一个普通字符,只能与-本身相匹配。所以,在正则中,- 字符不需要转义。
同一个字符集合里可以给出多个字符区间。[A-Za-z0-9]
取非匹配 ^
字符集合通常用来指定一组必须匹配其中之一的字符。但在某些场合,我们需要反过来做。换句话说,除了那个字符集合里的字符,其他字符都可以匹配。
元字符^对一个字符集合进行取非匹配
^的效果将作用于给定字符集合里所有字符或者字符区间,而不是仅限于紧跟在^字符后面的那一个字符或者区间。
元字符大致可以分为两种:一种是用来匹配文本的(比如.),另一种是正则的语法所要求的的(比如[和])
匹配空白字符: 空格
\f 换页符
\n 换行符
\r 回车符
\t 水平制表符
\v 垂直制表符
Windows中文本行结束标签 \r\n 空行 \r\n\r\n
Unix / Linux中文本行结束标签 \n 空行 \n\n
匹配特定的字符类:
匹配数字(与非数字):
\d 匹配任何一个数字字符(等价于[0-9])
\D 匹配任何一个非数字字符(等价于[^0-9])
(对同样的问题几乎总是有好几种不同的解决方法,这些方法并无优劣之分,你尽可以选择最熟悉的那种语法)
匹配字母和数字(与非字母和数字):
\w 匹配任何一个字母(大小写均可)、数字、以及下划线字符
(等价于[a-zA-Z0-9_])
\W 匹配任何一个非字母、数字、下划线字符
(等价于[^a-zA-Z0-9_])
匹配空白字符(与非空白字符):
\s 匹配任何一个空白字符(等价于[\f\r\n\t\v])
\S 匹配任何一个非空白字符(等价于[^\f\r\n\t\v])
匹配十六进制或八进制数值:
十六进制:前缀 \x 后面跟2位16进制 \x41
八进制:前缀 \0 数值本身可以是两位或者三位
前缀 \c 用来指定各种控制字符(比如\cZ将匹配Ctrl+Z)
POSIX字符类:
[:digit:] 匹配任何一个数字
[:alpha:] 匹配任何一个字母
[:alnum:] 匹配任何一个字母或数字
[:lower:] 匹配任何一个小写字母
[:upper:] 匹配任何一个大写字母
[:blank:] 匹配空格或者制表符 (等价于[\t ])
[:space:] 匹配任何一个空白字符 (等价于[\f\r\n\t\v ])
[:xdigit:] 匹配任何一个十六进制数 (等价于[a-fA-F0-9])
[:print:] 匹配任何一个可打印字符
[:cntrl:] 匹配任何一个ASCII控制字符(ASCII 0 ~ 31,加上ASCII 127)
[:graph:] 跟[:print:]一样,但不包括空格
[:punct:] 匹配既不属于[:alnum:]也不属于[:cntrl:]的任何一个字符
用法:[[:digit:]],外层的[和]字符用来定义一个字符集合,内层的[和]字符是POSIX字符类本身的组成部分
匹配一个或多个字符/字符集合:+
匹配至少一个;
用法:在字符后面加上一个 + 字符作为后缀即可
用于字符集合的话,要写在字符集合的外面,要不然最终结果就是匹配+
匹配零个或多个字符/字符集合:*
可有可无
匹配零个或一个字符:?
匹配空白行,同时适用于Windows和Unix以及Linux中的正则为:
[\r]?\n[\r]?\n == \r?\n\r?\n
[]常规用法是把多个字符定义为一个集合,但有不少程序员喜欢把一个字符也定义为一个集合。这么做的好处是可以增加可读性和避免产生误解。
匹配指定重复次数:
为重复匹配次数设定一个精确的值:{3}
意思是:{3}的前一个字符(字符集合)必须在文本里连续重复出现3次才算是一个匹配
为重复匹配次数设定一个区间:{3,5}
意思是:最少重复3次,最多重复5次
匹配“至少重复多少次”:{3,}
意思是:必须重复3次或更多次
防止过度匹配:
*、+以及{n,}都是“贪婪型”元字符,它们在进行匹配时的行为模式是多多益善而不是适可而止。它们会尽可能地从一段文本的开头一直匹配到这段文本的末尾,而不是从这段文本的开头匹配到碰到第一个匹配时为止。
在不需要这种“贪婪行为”时,可以使用这些字符的“懒惰型”版本(这里的“懒惰”是指匹配尽可能少的字符)
* *?
+ +?
{n,} {n,}?
位置匹配:
用来解决在什么地方进行字符串匹配操作的问题
单词边界:\b与\B
\b匹配这样一个位置:这个位置位于一个能够用来构成单词的字符(\w)
和一个不能用来构成单词的字符(\W)之间。 ——这个位置前后字符性质相反(一边是\w和另一边是\W)
\B不匹配一个单词边界。 ——这个位置前后字符性质一样(两边要么都是\w,要么都是\W)
有些匹配工具还支持:
\<匹配单词开头,
\>匹配单词末尾。
字符串边界:^和$
匹配的位置位于总文档的开头和末尾。
分行匹配模式:(?m)
(?m)使得正则把行分隔符当作一个字符串分隔符来对待。
(?m)必须出现在整个模式的最前面
^不仅匹配正常的字符串开头,还将匹配行分隔符后面的开始位置(不可见)
$不仅匹配正常的字符串结尾,还将匹配行分隔符后面的结束位置(不可见)
有些匹配工具还支持:
\A匹配字符串开头,
\Z匹配字符串结尾。
(但不支持(?m)分行匹配模式)
子表达式:()
把一个表达式划分为一系列子表达式的目的是为了把那些子表达式当作一个独立元素来使用。
例子:( ){2,}
(\d{1,3}\.){3}\d{1,3}
为了提高可读性,有不少用户喜欢给表达式的每一个子表达式都加上括号。比如,
(\d{1,3}\.){3}(\d{1,3})。这种做法在语法上完全成立,对表达式的实际行为也没有任何不良影响,但视乎具体的正则实现,这对匹配操作的速度可能会有点影响)
如果我们想匹配一个以19或20开头的4位数的年份数字,怎么做呢?
19|20\d{2}将匹配19或20\d{2}, | 字符是正则里的或操作符,它会把位于它左边和右边的两个部分都作为一个整体来看待。所以,我们需要这样做(19|20)\d{2}
子表达式嵌套:允许多重嵌套,理论上没有限制,但在实际工作中还是应该适可而止的原则。
(在分析各个子表达式的时候,应该按照先内后外的原则来进行而不是从第一个字符开始一个字符一个字符地去尝试)
(把必须匹配的情况考虑周全并写出一个匹配结果符合预期的正则表达式很容易,但把不需要匹配的情况也考虑周全并确保它们都将被排除在匹配结果以外往往要困难得多)
(在构造一个正则表达式的时候,一定要把你想匹配什么和你不想匹配什么详尽地定义清楚)
回溯引用:前后一致匹配
文本:This is a block of of text,
模式:[ ]+(\w+)[ ]+\1
回溯引用指的是模式的后半部分引用在前半部分中定义的子表达式。
回溯引用匹配通常以1开始计数。在许多实现里,第0个匹配可以用来代表整个正则表达式。
回溯引用可以跨模式,比如在查找使用子表达式,然后在替换中使用回溯引用。
替换中的大小写转换:
\l 把下一个字符转换为小写
\u 把下一个字符转换为大写
\L 把\L到\E之间的字符全部转换为小写
\U 把\U到\E之间的字符全部转换为大写
\E 结束\L或\U转换
前后查找:
(有些正则表达式文档使用术语“消费”来表述“匹配和返回文本”的含义,在前后查找中,被匹配的文本不包含在最终返回的匹配结果里,称之为“不消费”)
向前查找:(?=)
用法:.+(?=:)把需要匹配的文本放在 = 后即可。
(向:之前查找,返回的结果不包括:)
(向前查找和向后查找匹配本身其实是有返回值的,只是这个返回值的字节长度永远为0而已,所以,前后查找有时也被称为零宽度匹配操作)
向后查找:(?<=)
用法:(?<=\$)[0-9.]+把需要匹配的文本放在 = 后即可。
(向$之后查找,返回的结果不包括$)
(向前查找模式长度是可变的;向后查找模式长度只能是固定的)
对前后查找取非:
(?=) 正向前查找 匹配、匹配,一直到:为止(不包括:)
(?!) 负向前查找 匹配、匹配,不用到:为止
(?<=) 正向后查找 找到$,在它之后进行匹配
(?<!) 负向后查找 不要找到$,在除了$以外的字符后面匹配
嵌入条件:
两种情况:
1,根据一个回溯引用来进行条件处理
2,根据一个前后查找来进行条件处理
1.1回溯引用条件
(只在一个前面的子表达式搜索取得成功的情况下才允许使用一个表达式)
(?(1)true-regex | false-regex)
?(1)检查第一个回溯引用是否存在。若存在,执行true-regex;若不存在,执行false-regex
2.1前后查找条件
(只在向前或向后查找操作取得成功的情况下才允许一个表达式被使用)
(?(前后表达式)true-regex | false-regex)