Regex
regular expressions
先理解什么是正则表达式, 有什么用途
理解: 是表达一类串的抽象模式的串, 来匹配字符串中符合模式的子串
人话: 举例, 例如abc9
, abcd9
, a&*&%*()9
, 这三个字符串有相同的模式(人话来说就是他们有共同点): 都以a开头, 9结尾. 正则表达式就能用来表示这种以a开头, 9结尾的模式(共同点), 来匹配这一类字符串.
a开头, 9结尾的模式用正则表达式表示就是:
a.*9
一个正则表达式在线练习网站 https://regex101.com
字面模式
理解: 用一种模式表达的一个字符
1. 字面值字符
比如字母, 数字, 空格, 或者特殊符号, 匹配的是确定的字符串, 比如正则表达式abc
, 会在12312124abcefgabc
中匹配连续的abc
三个字符, 这没有什么模式可言, 就是固定的搜索
一般和下面的搭配才能表示模式
下面提到的特殊符号, 如果要直接匹配, 要加一个转义
比如要匹配
(/123-456)
正则表达式要写
\(\/123\-456\)
2. [ ]
用于自定义一个字符集合, 字符集合中任选一个字符都可以用来用来匹配
比如[abc]123
,字符集合中有a, b, c, 这三个字符的任意一个都可以用来匹配, 所以可以匹配a123
, b123
, c123
, 但d123
不行
接下来就介绍各种各样的字符集合表示方式
(1) 直接枚举
[abcdefg]
:字符集合中的任意一个字符都可以用来用来匹配
(2) 范围:
中括号中加-
代表范围, [a-g]
就等同于[abcdefg]
(3) 排除:
中括号中加^
代表, 除了你定义的集合以外的字符都可以匹配,
比如[^1-3]
相当于除了123都可以匹配上
3. \d
, \w
, \s
, \n
等
就是已经定义过的一些认为是一类字符的字符
最常用的就是\d, \w, \s, \n
- \d 匹配一个数字字符。等价于 [0-9]。
- \w 匹配字母、数字、下划线。等价于’[A-Za-z0-9_]’
- \s 匹配任何空白字符, 等价于 [ \f\n\r\t\v]。
- \n 匹配换行符
\d | 匹配一个数字字符。等价于 [0-9]。 |
---|---|
\D | 匹配一个非数字字符。等价于 [^0-9] 。 |
\f | 匹配一个换页符。等价于 \x0c 和 \cL。 |
\n | 匹配一个换行符。等价于 \x0a 和 \cJ。 |
\r | 匹配一个回车符。等价于 \x0d 和 \cM。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v] 。 |
\t | 匹配一个制表符。等价于 \x09 和 \cI。 |
\v | 匹配一个垂直制表符。等价于 \x0b 和 \cK。 |
\w | 匹配字母、数字、下划线。等价于’[A-Za-z0-9_]'。 |
\W | 匹配非字母、数字、下划线。等价于 [^A-Za-z0-9_] 。 |
\xn | 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,‘\x41’ 匹配 “A”。‘\x041’ 则等价于 ‘\x04’ & “1”。正则表达式中可以使用 ASCII 编码。 |
\num | 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,‘(.)\1’ 匹配两个连续的相同字符。 |
\n | 标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。 |
\nm | 标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。 |
\nml | 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。 |
\un | 匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)。 |
4. .
匹配任何除了换行的字符
等价于[^\n\r]
限定符: 表示数量的模式
理解: 指定限定符前面的一个普通字符的匹配个数
比如abc+
, +
是一个限定符, 只限定左边的一个模式也就是c
, +
的意思是限定c
出现的次数为1次到任意多次, 也就是abc
, abcccccccccc
, abccc
都会匹配上
1. *
: 0次或多次
2. +
: 1次或多次
3. ?
: 0次或1次
4. {n}
: 指定匹配确定的n次,
5. {n, }
: 指定至少n次(n次或多次),
6. {n, m}
: 指定最少n次最多m次
7. 贪婪/非贪婪匹配: *?
, +?
贪婪/非贪婪理解:一个带*
和+
的regex可能匹配到多个不同长短的字符串, 贪婪和非贪婪分别就是指定 取这些不同长短字符串中 最长的还是最短的, +
, *
都是贪婪的(会尽可能多的匹配),后面加上?
就能指定匹配最短的
看个例子就能理解
string: <h1>hello</h1>
regex1: <.*>
:
<h1>hello</h1>
和<h1>
都是符合匹配模式的, 但*会匹配尽可能多的字符, 所以最后的匹配结果是 <h1>hello</h1>
regex2: <.*?>
:
<h1>hello</h1>
和<h1>
都是符合匹配模式的, 相反*?
会匹配尽可能少的字符, 所以最后的匹配结果是 <h1>
定位符
1. 理解:
定位符也是一个模式, 但是不匹配具体的字符匹配的是一个位置, 比如^
就是匹配待匹配字符串的最开头的那个位置, 整个字符串的最开头就只有一个,
2. 用法速看
^
: 匹配字符串开始的位置
$
: 匹配字符串结尾的位置
\b
: 匹配字与空格间的那个位置
\B
: 坚决不匹配字与空格间的那个位置
\B举例:
string: aptitude chapter
regex: \Bapt
就不会匹配到aptitude的apt, 因为apt是字与空格间的那个位置
选择: ()
1. 分组
理解: 用()
括起来的模式串会匹配多个弄成一个可以访问的数组
2. 限定前后内容:
1. 简单介绍用途, 不想看直接看下面的表
想要在字符串 [email protected], [email protected], 13312312312
中匹配qq邮箱的qq号
不正确的正则1号: \d+
, 字符串中所有的数字都被匹配到了, 包括最后的电话号码
不正确的正则2号: \[email protected]
, 这下只会匹配到[email protected], 但是我们要求只要前面的qq号, 不要多余的@qq.com
正确的正则3号: \d+([email protected])
, 要求后面有@qq.com, 但不把@qq.com匹配进去
2.用法速看
匹配括号前面 | 匹配括号后面 | |
---|---|---|
满足括号里模式的前提下匹配(但是不匹配括号里的内容) | ?= | ?<= |
满足括号里模式时不匹配 | ?! | ?<! |
比如
(?<=\d+)abc(?!\d)
要求abc前面必须有至少一个数字, 后面不能有数字
或: |
比较简单, 直接举例
待匹配字符串abcdefg
正则表达式:abc | efg
就是匹配abc或者efg, 二者其一匹配上都行
就会得到 abcdefg
练习:
简单模式
匹配所有qq邮箱的用户名
[email protected] [email protected]
123-1h@ @qq.com [email protected]
答案
[\-\w]+([email protected])
困难模式:
匹配C, C++中的单行注释和多行注释
#include "lib/mylib.hpp"
#include <string>
int main() {
std::string s = "no ! // this is not a comment";
int a = 5; // this is a inline comment
// another inline comment // don't split it
///another comment //
//
// this ";" punctuation is called semicolon
/* a multiline comment is surrounded by
a pair of /*
and */
std::string warning = "don't combine these two multiline comment"
/* a multiline comment is surrounded by
a pair of /*
and */
}