正则表达式
# 正则表达式
Owner: -QVQ-
# 正则表达式
^ 为匹配输入字符串的开始位置
- [0-9]+匹配多个数字, [0-9] 匹配单个数字,+ 匹配一个或者多个。
- abc$匹配字母 abc 并以 abc 结尾,$ 为匹配输入字符串的结束位置。
如上部分能实现只包含字符、数字、下划线、连接符- ,并设置字符长度为3-15的字符串查找
| 类型匹配 | \d | 数字 | |
|---|---|---|---|
| \D | 非数字 | ||
| \w | 字母+数字+下划线_ | ||
| \W | 除了字母+数字+下划线_ | ||
| . | 任意(除了换行符) | ||
| \s | 匹配空白符(换行符、制表等等 ) | 等价于 [ \f\n\r\t\v] | |
| \S | 除了空白和换行符的内容 | ||
| 限定符(数量匹配) | 匹配前面的模式几次 | 限定符与定位符不能一起使用 | |
| * | 0-∞ | ||
| + | 1-∞ | ||
| ? | 0-1 | ||
| {n} | n | ||
| {n,} | n-∞ | ||
| {n,m} | [n,m) | ||
| \n | 如果前面有n个表达式,则为引用 | ||
| 如果前面没有,则为匹配8进制的数字 | |||
| 具体字符匹配 | [abc] | 匹配a或b或c | |
| [^abc] | 除了abc以外的任意字符 | ||
| [A-Z] | 匹配A-Z区间的字符 | ||
| 特殊字符 | \: | 转义字符,匹配:本身 | |
| 匹配逻辑 | () | 标记一个字表达式的开始和结束 | |
| 指名两项之间选择一个 | |||
| 定位符 | $ | 匹配字符串的结尾 | 若要一个字符串只包含指定内容,前后没有其他内容,例如,想匹配Chapter 1时 匹配语法:^Chapter [1-9][0-9]{0,1} 会匹配到abcChapter 1abc 修改匹配语法:^Chapter [1-9][0-9]{0,1}$ |
| ^ | 匹配字符串的开始 | ||
| \b | 匹配一个单词边界,即字与空格间的位置。 | 匹配字符串:Chapter 1匹配语法:\bCha 或 \ter\b/ | |
| \B | 非单词边界匹配 | 匹配字符串:Chapter 1匹配语法:\Bapt 不匹配语法:\BCha | |
| 其他 | \cx | 匹配由 x 指明的控制字符 | 例如, \cM 匹配一个 Control-M 或回车符 |
| \f | 匹配一个换页符。等价于 \x0c 和 \cL。 | ||
| \n | 匹配一个换行符。等价于 \x0a 和 \cJ。 | ||
| \r | 匹配一个回车符。等价于 \x0d 和 \cM | ||
| \t | 匹配一个制表符。等价于 \x09 和 \cI。 | ||
| \v | 匹配一个垂直制表符.等价于 \x0b 和 \cK。 | ||
| \xn | 匹配16进制的n,n必须是两位数 |
最小匹配语法:
*和+默认会匹配最长的字符串,如果要最小匹配,在其后面加?。例如
对于字符串:<h1>RUNOOB-菜鸟教程</h1>
匹配语法:<.*> 匹配结果:<h1>RUNOOB-菜鸟教程</h1>
匹配语法:<.*?> 匹配结果:<h1>
例子:
匹配1-99:[1-9][0-9]?
# 反向引用
(exp)能将相关匹配存储到临时缓存区中,通过\n来访问这些临时缓存区,最多支持99。
可以用非捕获元来重写捕获
| 非捕获元 | ?: | 不捕获匹配缓存 | 字符串:"1234ru124run34”匹配字符:([1-9])([a-z])+匹配结果:[('4', 'u'), ('4', 'n')]每个()匹配的结果会被缓存,因此用?:消除缓存字符串:"1234ru124run34”匹配字符:(?:[1-9])(?:[a-z])+匹配结果:['4ru', '4run'] |
|---|---|---|---|
| ?= | **exp1(?=exp2)**查找 exp2 前面的 exp1 | 字符串:"1234ru124rn34”匹配字符:ru(?=[0-9])匹配结果:ru | |
| ?<= | **(?<=exp2)exp1**查找 exp2 后面的 exp1。 | 字符串:"1234ru124rn34”匹配字符:(?<=[0-9])ru匹配结果:ru | |
| ?! | **exp1(?!exp2)**查找后面不是 exp2 的 exp1。 | ||
| ?<! | **(?<!exp2)exp1**查找前面不是 exp2 的 exp1。 |
例子:
匹配字符:"Is is the cost of a of gasoline going up up”
匹配语法:(\b[a-z]+\b) \1
匹配逻辑等同于如下
//str[i]存放一个单词
while(i<str.size()){//当使用的是正则表达式的多次匹配时,会有这个while,如果是单次顺序匹配就没有这个
int j=i;
while(str[i] == str[j])j++;//不管外层使用的是多次匹配还是单词匹配,内部走的都是单次顺序匹配的逻辑
if(j!=i)cout<<str[i];
i=j+1;
}
2
3
4
5
6
7
测试例子python
# /home/admin/mytest/regex/regex.py import re line = "https://www.runoob.com:80/html/html-tutorial.html" matchObj = re.findall( r'(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)', line) print(matchObj) # [('https', 'www.runoob.com', ':80', '/html/html-tutorial.html')] matchObj2 = re.findall( r'(?:\w+):\/\/(?:[^/:]+)(?::\d*)?(?:[^# ]*)', line) print(matchObj2) str = "Is is the cost of of gasoline going up up up" print(re.findall(r'\b([a-z]+) \1\b', str)) # ['of', 'up'] print(re.findall(r'\b([a-z]+)\1\b', str)) # [] 将Is和空格进行比较,空格又和is进行比较,所以没有匹配 print(re.findall(r'(\b[a-z]+\b) \1', str)) # ['of', 'up'] print(re.findall(r'\b([a-z]+)\b \1', str)) # ['of', 'up'] str = "Is is the cost of a of gasoline going up up" print(re.findall(r'(\b[a-z]+\b) \1', str)) # [ 'up'] print(re.findall(r'\b([a-z]+)\b(?:.*?\b\1\b)+', str)) # ['of', 'up'] print(re.findall(r'(\b[a-z]+\b) \1', str, re.I)) # ['Is', 'up'] str = "Is is the cost of a of gasoline going up up" print(re.findall(r'up', str)) # 当调用findall时,他能帮我去多次查找字符串中的所有匹配项 # 但是每个子匹配项调用的是match,所以只能匹配到第一个匹配项1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 优先级表
| 运算符 | 描述 |
|---|---|
| \ | 转义符 |
| (), (?😃, (?=), [] | 圆括号和方括号 |
| *, +, ?, {n}, {n,}, {n,m} | 限定符 |
| ^, $, \任何元字符、任何字符 | 定位点和序列(即:位置和顺序) |
# python使用正则
import re
# re.match函数
re.match(pattern, string, flags=0)
从字符串的起始位置匹配一个,如果匹配失败返回none
line = "Cats are smarter than dogs"
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
print "matchObj.group() : ", matchObj.group() # Cats are smarter than dogs
print "matchObj.group(1) : ", matchObj.group(1) # Cats
print "matchObj.group(2) : ", matchObj.group(2) # smarter
else:
print "No match!!"
2
3
4
5
6
7
8
9
10
# re.search函数
扫描整个字符串并返回第一个成功的匹配。
re.search(pattern, string, flags=0)
返回对象同上
# re.sub函数
替换字符串中的匹配项
re.sub(pattern, repl, string, count=0, flags=0) count表示替换次数
import re
phone = "2004-959-559 # 这是一个国外电话号码"
# 删除字符串中的 Python注释
num = re.sub(r'#.*$', "", phone)
print "电话号码是: ", num
2
3
4
5
6
7
# re.findall函数
找到正则表达式所匹配的所有子串,并返回一个列表
有多个匹配模式,则返回元组列表
# 可选标识
| 修饰符 | 描述 |
|---|---|
| re.I(大写i) | 不区分大小写 |
| re.L | 做本地化识别(locale-aware)匹配 |
| re.M | 多行匹配,影响 ^ 和 $ |
| re.S | 使 . 匹配包括换行在内的所有字符 |
| re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
| re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
# cpp正则库
Owner: -QVQ-
#include<regex>
regex reg("") 构建用于匹配正则的表达式。
regex_search(s, result, reg) 从字符串s中依照正则表达式reg规则匹配字符串,匹配到的结果放入字符串result中
例子
#include <iostream> #include <iterator> #include <string> #include <regex> using namespace std; int main() { // 目标序列 string s = "Some people, when confronted with a problem, think "; // 结果集 smatch result; // 模式串 regex reg("(\\w{5,})"); /* 5个以上的长单词 */ // 匹配 regex_search(s, result, reg); // 只匹配一个结果 cout << result[0] << endl; // 利用迭代器,反复匹配达到全局(\g)匹配的效果 for (sregex_iterator it(s.begin(), s.end(), reg), end_it; it != end_it; ++it) { cout << it->str() << " "; } cout << endl; // 或者使用循环的方式,多次调用regex_search while (regex_search(s, result, reg)) { std::cout << result.str() << " "; s = result.suffix(); } cout << endl; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
string new_s = regex_replace(s, reg, "[$&]");
在字符串s中以正则表达式reg的规则匹配字符串,用[$&] 来替代这个字符串,返回替换后的s给new_s
std::sregex_iterator 迭代器,指向由指定规则筛选得到的捕获组
//input为要处理的字符串,func_regex为筛选的正则表达式规则
std::sregex_iterator func_it(input.begin(), input.end(), func_regex);
//func_it指向根据func_regex规则筛选出来的多个捕获组
std::sregex_iterator func_end;
for(;func_it != func_end; func_it++){
//对每一个捕获组进行操作
}
2
3
4
5
6
7
