正则表达式
定义:正则表达式是一组由字母和符号组成的特殊文本, 它可以用来从文本中找出满足你想要的格式的句子。
一个正则表达式是在一个主体字符串中从左到右匹配字符串时的一种样式。"Regular expression" 这个词比较拗口, 我们常使用缩写的术语 "regex" 或 "regexp" 。 正则表达式可以从一个基础字符串中根据一定的匹配模式替换文本中的字符串、验证表单、提取字符串等等。
想象你正在写一个应用, 然后你想设定一个用户命名的规则, 让用户名包含字符、数字、下划线和连字符,以及限制字符的个数,好让名字看起来没那么丑。我们使用以下正则表达式来验证一个用户名:
以上的正则表达式可以接受 john_doe, jo-hn_doe, john12_as。但不匹配 Jo , 因为它包含了大写的字母而且太短了。
1. 基本匹配
正则表达式其实就是在执行搜索时的格式, 它由一些字母和数字组合而成。例如:一个正则表达式 the, 它表示一个规则: 由字母 t 开始,接着是 h ,再接着是 e 。
注意:正则表达式是大小写敏感的
2. 元字符
正则表达式主要依赖于元字符。元字符不代表他们本身的字面意思, 他们都有特殊的含义。 一些元字符写在方括号中的时候有一些特殊的意思。以下是一些元字符的介绍:
2.1 点运算符 .
. 是元字符中最简单的例子。. 匹配任意单个字符, 但不匹配换行符。例如, 表达式 .ar 匹配一个任意字符后面跟着是 a 和 r 的字符串。
2.2 字符集
字符集也叫做字符类。方括号用来指定一个字符集。在方括号中使用连字符来指定字符集的范围。在方括号中的字符集不关心顺序。例如, 表达式 [Tt]he 匹配 the 和 The 。
方括号的 "." 就表示 "." 。表达式 ar[.] 匹配 ar. 字符串。
2.3 否定字符集
一般来说 ^ 表示一个字符串的开头, 但它用在一个方括号的开头的时候, 它表示这个字符集是否定的。例如, 表达式 [^c]ar 匹配一个后面跟着 ar 的除了 c 的任意字符。
2.4 * 号
* 号匹配在 * 之前的字符出现大于等于 0 次。例如, 表达式 a* 匹配以 0 或更多个 a 开头的字符, 因为有 0 个这个条件, 其实也就匹配了所有的字符。表达式 [a-z]* 匹配一个行中所有以小写字母开头的字符串。
* 字符和 . 字符搭配可以匹配所有的字符 .* 。 * 和表示匹配空格的符号 \s 连起来用, 如表达式 \s*cat\s* 匹配 0 或更多个空格开头和 0 或更多个空格结尾的 cat 字符串。
2.5 + 号
+ 号匹配 + 号之前的字符出现 >=1 次的字符. 例如表达式 c.+t 匹配以首字母 c 开头以 t 结尾,中间跟着任意个字符的字符串。
2.6 ? 号
在正则表达式中元字符 ? 标记在符号前面的字符为可选,即出现 0 或 1 次。例如,表达式 [T]?he 匹配字符串 he 和 The 。
2.7 {} 号
在正则表达式中 {} 是一个量词, 常用来一个或一组字符可以重复出现的次数。例如, 表达式 [0-9]{2,3} 匹配 2~3 位 0~9 的数字。
我们可以省略第二个参数。例如,[0-9]{2,} 匹配至少两位 0~9 的数字。
如果逗号也省略掉则表示重复固定的次数。例如, [0-9]{3} 匹配 3 位数字。
2.8 (...) 特征标群
特征标群是一组写在 (...) 中的子模式。例如之前说的 {} 是用来表示前面一个字符出现指定次数。但如果在 {} 前加入特征标群则表示整个标群内的字符重复 N 次。例如, 表达式 (ab)* 匹配连续出现 0 或更多个 ab 。
我们还可以在 () 中用或字符 | 表示或。例如, (c|g|p)ar 匹配 car 或 gar 或 par 。
2.9 | 或运算符
或运算符就表示或, 用作判断条件。例如 (T|t)he|car 匹配 (T|t)he 或 car 。
2.10 转码特殊字符
反斜线 \ 在表达式中用于转码紧跟其后的字符。用于指定 { } [ ] / \ + * . $ ^ | ? 这些特殊字符。如果想要匹配这些特殊字符则要在其前面加上反斜线 \ 。例如 . 是用来匹配除换行符外的所有字符的。如果想要匹配句子中的 . 则要写成 \ 。以下这个例子 .? 是选择性匹配.
2.11 ^ 号
^ 用来检查匹配的字符串是否在所匹配字符串的开头。例如, ^(T|t)he 匹配以 The 或 the 开头的字符串。
2.12 $ 号
同理于 ^ 号, $ 号用来匹配字符是否是最后一个。例如, (at\ .)$ 匹配以 at. 结尾的字符串。
3. 简写字符集
正则表达式提供一些常用的字符集简写,如下:
4. 前后关联约束(前后预查)
前置约束和后置约束都属于非捕获簇(用于匹配不在匹配列表中的格式)。前置约束用于判断所匹配的格式是否在另一个确定的格式之后。
例如, 我们想要获得所有跟在 $ 符号后的数字, 我们可以使用正向向后约束 (?<=$)[0-9\ .]*. 这个表达式匹配 $ 开头, 之后跟着 0,1,2,3,4,5,6,7,8,9。这些字符可以出现大于等于 0 次。
前后关联约束如下:
4.1 ?=... 前置约束-存在
前置约束-存在 ?=... 表示第一部分表达式必须跟在 ?=... 定义的表达式之后。返回结果只返回第一部分表达式。定义一个前置约束-存在要使用 () 。在括号内部使用一个问号和等号:(?=...) 。前置约束的内容写在括号中的等号后面。例如, 表达式 [T|t]he(?=\ sfat) 匹配 The 和 the, 在括号中我们又定义了前置约束-存在 (?=\ sfat) , 即 The 和 the 后面紧跟着 (空格)fat 。
4.2 ?!... 前置条件-排除
前置约束-排除 ?!... 用于筛选所有匹配结果, 筛选条件为其后不跟随着定义的格式。 前置约束-排除 定义和 前置约束-存在 一样, 区别就是 = 替换成 ! 也就是 (?!...) 。例如,表达式 [T|t]he(?!\ sfat) 匹配 The 和 the, 且其后不跟着 (空格)fat 。
4.3 ?<=... 后置约束-存在
后置约束-存在 ?<=... 用于筛选所有匹配结果, 筛选条件为其前跟随着定义的格式。例如, 表达式 (?<=[T|t]he\ s)(fat|mat) 匹配 fat 和 mat, 且其前跟着 The 或 the 。
4.4 ?<!... 后置约束-排除
后置约束-排除 ?<!... 用于筛选所有匹配结果, 筛选条件为其前不跟着定义的格式。例如, 表达式 (?<!(T|t)he\ s)(cat) 匹配 cat, 且其前不跟着 The 或 the 。
5. 标志
标志也叫修饰语, 因为它可以用来修改表达式的搜索结果。这些标志可以任意的组合使用, 它也是整个正则表达式的一部分。
5.1 忽略大小写
修饰语 i 用于忽略大小写。例如, 表达式 /The/gi 表示在全局搜索 The, 在后面的 i 将其条件修改为忽略大小写, 则变成搜索 the 和 The, g 表示全局搜索。
5.2 全局搜索
修饰符 g 常用语执行一个全局搜索匹配, 即(不仅仅返回第一个匹配的, 而是返回全部)。例如, 表达式 /.(at)/g 表示搜索任意字符(除了换行) + at, 并返回全部结果。
5.3 多行修饰符
多行修饰符 m 常用语执行一个多行匹配。像之前介绍的 (^,$) 用于检查格式是否是在待检测字符串的开头或结尾. 但我们如果想要它在每行的开头和结尾生效, 我们需要用到多行修饰符 m 。例如, 表达式 /at(.)?$/gm 表示在待检测字符串每行的末尾搜索 at 后跟一个或多个 . 的字符串, 并返回全部结果。
参考资料:
learn-regex