1. 简介
Regex(Regular expressions),描述了一种字符串匹配的模式(pattern),可以用来检查一个字符串是否包含某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
2. 语法
基本的
符号 | 说明 | 例子 |
| | 选择,即或集 | gray|grey 可以匹配 grey 或 gray |
+ | 前边的字符出现1次或者多次 | |
? | 前边的字符出现0次或者1次 | |
* | 前边的字符出现0次、1次或者多次 | |
{n} | 重复 n 次 | |
{n,} | 重复 n 到 更多次 | |
{n,m} | 重复 n 到 m 次 | |
() | 定义操作的范围 | 1、(abc|bcd|cde),表示这一段是abc、bcd、cde三者之一均可,顺序也必须一致 2、(abc)?,表示这一组要么一起出现,要么不出现,出现则按此组内的顺序出现 3、(?:abc)表示找到这样abc这样一组,但不记录,不保存到$变量中,否则可以通过$x取第几个括号所匹配到的项,比如:(aaa)(bbb)(ccc)(?:ddd)(eee),可以用$1获取(aaa)匹配到的内容,而$3则获取到了(ccc)匹配到的内容,而$4则获取的是由(eee)匹配到的内容,因为前一对括号没有保存变量 4、a(?=bbb) 顺序环视 表示a后面必须紧跟3个连续的b 5、(?i:xxxx) 不区分大小写 (?s:.*) 跨行匹配.可以匹配回车符 |
[] | 单个匹配 | [0-3] 表示这个位置上必须是 0、1、2、3 |
[^x] | 匹配除了x以外的任意字符 | [^eiou] 匹配除了eiou这几个字母以外的任意字符 [^0-3]表示这个位置上是处理0到3之外的所有字符 |
元字符
代码 | 说明 | 例子 |
. | 匹配除换行符以外的任意字符 | |
\w | 匹配字母或数字或下划线或汉字 | ^\w+匹配一行的第一个单词(或整个字符串的第一个单词,具体匹配哪个意思得看选项设置) |
\W | 匹配任意不是 \w 的字符 | |
\s | 匹配任意的空白符 | |
\S | 匹配任意不是空白符的字符 | \S+匹配不包含空白符的字符串 |
\d | 匹配数字 | H(ae?|ä)ndel和H(a|ae|ä)ndel是相同的,表示{"Handel", "Haendel", "Händel"} |
\D | 匹配任意非数字的字符 | |
\b | 匹配单词的开始或结束 | |
\B | 匹配不是单词开头或结束的位置 | |
^ | 匹配字符串的开始 | |
$ | 匹配字符串的结束 |
常用分组语法
分类 | 代码/语法 | 说明 |
捕获 | (exp) | 匹配exp,并捕获文本到自动命名的组里 |
(?<name>exp) | 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp) | |
(?:exp) | 匹配exp,不捕获匹配的文本,也不给此分组分配组号 | |
零宽断言 | (?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 | |
匹配后面跟的不是exp的位置 | ||
(?!exp) | 匹配后面跟的不是exp的位置 | |
(?<!exp) | 匹配前面不是exp的位置 | |
注释 | (?#comment) | 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 |
3. 例子
3.1 python中的正则表达式
import re
# (1星号)(2大写字母/下划线)(忽略不索引)(3数字)(4问号)
patternB = re.compile(r'(\*?)([A-Z_]+)(?:[a-z_]*)([0-9]*)(\?)?', re.M)
result = patternB.search(':CHANnel')
if result != None:
a_para_0 = reuslt.group() // 匹配的所有
a_para_1 = reuslt.group(1)
a_para_2 = reuslt.group(2)
a_para_3 = reuslt.group(3)
a_para_4 = reuslt.group(4)
可以使用vscode进行单步调试,仿真结果
- a_para_0 是 'CHANnel1'
- a_para_1 是 ''
- a_para_2 是 'CHAN'
- a_para_3 是 '1'
- a_para_4 是 None (这里注意同 a_para_1 的区别)
小知识
re.M表示多行模式,当设置了后,'^'会匹配字符串的开始,和每一行的开始(换行符后紧跟的符号),$同理。
re.I表示忽略大小写,设置后不区分大小写。
在字符匹配中可能还会用到判断:
s = ...
判断是不是字母:s.isalpha()
判断是不是数字:s.isdigit()
判断是不是大写:s.isupper()
判断是不是小写:s.islower()
3.2 qt 中的正则表达式
// (1"<>"内的内容,这个因为外边的?要索引)(2{大括号内内容})(3()小括号内内容)(4"<>"内内容)(5<>后边的所有字母)
QRegExp reRoot("(?:(<\\s*\\w+\\s*>)::=)?\\s*\\{\\s*([\\w\\|-\\.]+)\\s*\\}\\s*(?:\\(((?:\\s*[\\w:]+\\s*,*\\s*)+)\\))?"
"|(?:(<\\s*\\w+\\s*>)::=)?\\s*(\\w+)$");
QString longName = "<mode>::={OFF|MANual|TRACk|AUTO|XY}(cursor_mode_off,cursor_mode_manual,cursor_mode_track,cursor_mode_auto,cursor_mode_xy)"
int pos = reRoot.indexIn(longName, 0);
if(pos != (-1))
{
a_0 = reRoot.cap(0); // 匹配的全部内容
a_1 = reRoot.cap(1); // ..
a_2 = reRoot.cap(2);
a_3 = reRoot.cap(3);
a_4 = reRoot.cap(4);
a_5 = reRoot.cap(5);
}
- a_0 是 "OFF|20M|25M|50M|70M|100M|150M|200M|300M|350M|500M|600M|1G|2G|4G|5G|10G|20G}(BW_OFF,BW_20M,BW_25M,BW"
- a_1 是 ""
- a_2 是 "OFF|20M|25M|50M|70M|100M|150M|200M|300M|350M|500M|600M|1G|2G|4G|5G|10G|20G"
- a_3 是 "BW_OFF,BW_20M,BW_25M,BW_50M,BW_70M,BW_100M,BW_150M,BW_200M,BW_300M,BW_350M,BW_500M,BW_600M,BW_1G,BW_"
- a_4 是 ""
- a_5 是 ""