正则表达式
- 元字符
- \b 只是匹配开头或结尾的一个位置,而不是代表空格,点,换行符等;
- 示例:如果要匹配 hi 后面不远处是否有跟着一个单词 Lucy,则可以考虑这么写:\bhi\b.*\bLucy\b
- 点“.”可以用来匹配除了换行符以外的任何字符;星号“”代表的是数量,表示星号前面的内容可以连续重复任意次,所以二者合起来的“.*" 表示任意数量的不包含换行的字符;“+” 表示重量1次或更多次,星号可以匹配0次,但加号不行,“\d+” 表示匹配一个或者多个数字;如果要表示"." 本身,则需要使用 .
- \d 匹配一位数字,0,或1,或2,或3
- 示例1:0\d\d\d-\d\d\d\d\d\d\d,表示匹配 0 开头的,接下来3位数字,接着使用横杠连接着,后面接着7位数字的字符串,显然,可以用来表示座机号码,例如 0755-3819783
- 示例2:示例1的简化版,0\d{3}-\d{7}
- \w 匹配字母或数字或下划线或汉字
- \s 匹配任意的空白符,包括空格,制表符tab,换行符,中文全角空格等;
- ^ 匹配字符串的开始;$ 匹配字符串的结束;
- 示例1
- 问题:网站要验证输入的 QQ 号是5-12位的
- 答案:^\d{5,12}$
- 其他:
- 有些正则表达式的处理工具还有一个处理多行的情况,如果选中了这个选项,则 ^ 和 $ 的含义变成了匹配行的开始处和结束处;
- 示例1
- \b 只是匹配开头或结尾的一个位置,而不是代表空格,点,换行符等;
- 字符转义
- 因为一些元字符代表了某种特别的含义,但当你想查找它们本身的话,就需要一个特殊的字符斜杠 "" 来取消它们代表的特殊含义;
- 重复
- ? 表示重复一次或零次;
- {n,} 重复 n 次或者更多次
- {n,m} 重复 n 到 m 次;
- 字符类
- 方括号可以用来表示整体的字符集
- 示例1:[aeiou] 表示匹配方括号中5个元音字母的任意一个
- 示例2:[.?!] 表示匹配方括号中点号、问号、感叹号等3个符号的任意一个
- 示例3:[0-9] 表示匹配 0 到 9 的任意一个数字,与 \d 是相同的意思;同理,[0-9a-zA-Z] 则等同于 \w (如果只考虑英文,不考虑汉字或下划线的话)
- 示例4:(?0/d{2}[) -]?\d{8},转义一个左括号,出现1次或不出现,接着2个数字,接着右括号、空格、中横杠 3 个中的 1 个或者不出现,接着 8 个数字;
- 方括号可以用来表示整体的字符集
- 分枝条件
- 使用竖线来代表分枝条件,注意顺序很重要,即会先判断左边的分枝是否满足,如果满足,则不再检查右边的分枝;如果不满足,则再检查右边的分枝是否满足;
- 分组
- 通过使用括号来对多个字符归成一组,然后可以对整组字符做操作,例如设定重复次数;
- 括号内的分组,也可以视同一个子表达式;
- 正则表达式中不能使用数学计算;
- 反义
- \W,匹配任意不是字母、数字、汉字、下划线的字符;
- \S,匹配任意不是空白的字符;
- \D,匹配任意不是数字的字符;
- \B,匹配任意不是开头或结尾的字符;
- [^x],匹配不是 x 的字符;
- [^aeiou],匹配不是 aeiou 这5个字符的任意字符;
- 示例
- \S+,匹配不包含空白字符的字符串;
- <a[^>]+>,匹配不包含右尖括号的,以 <a 开头,以 > 结尾的字符串;
- 后向引用
- 每个分组会有一个组号,从左往右,组号从1开始编号,第一组的组号为1,第二组的组号为2,以此类推;分组 0 则对应整个正则表达式;
- 组号分析的工作原理,是要扫描两遍的:
- 第1遍:扫描找出所有未命名的组,给它们依次编号;
- 第2遍:扫描找出所有已命名的组,给它们依次编号(接着第1遍的编号往下)
- 因此,所有已命名组的组号都是大于未命名的组的;
- 给分组命名的两种办法:
- 办法1:(?<组名>表达式)
- 办法2:(?'组名’表达式)
- 通过引用分组号或者分组名,可以重复引用分组捕获的内容
- 示例:\b(\w+)\b\s+\1\b,此处的\1表示重复前面的分组(\w+)捕获的内容;
- 重复引用的好处是可以让表达式写得更加简洁和易于维护;
- 当分组有自定义的名称时,引用的办法是:\k<组名>
- 常用分组语法:
- 捕获
- (exp),匹配 exp,并捕获文本到自动命名的组里;
- (?
exp),匹配 exp,并捕获文本到命名为 name 组里; - (?:exp),匹配 exp,但不捕获文本到自动命名的组里,也不给此分组分配组号;
- 零宽断言(#好高深的名称,什么鬼?)
- (?=exp),匹配 exp 前面的位置;
- (?<=exp),匹配 exp 后面的位置;
- (?!exp),匹配后面跟的不是 exp 的位置;
- (?<exp),匹配前面跟的不是 exp 的位置;
- 注释
- (?#注释内容),表示一个注释,仅阅读,不产生任何作用或副作用;
- 捕获
- 零宽断言
- (?=exp),零宽度正预测先行断言,它断言自身出现位置的后面,能匹配表达式 exp
- 示例:\b\w+(?=ing\b),匹配以 ing 结尾的单词的前面部分
- I’m singing while you’re dancing
- 匹配 sing 和 danc
- 示例:\b\w+(?=ing\b),匹配以 ing 结尾的单词的前面部分
- (?<=exp),零宽度正回顾后发断言,它断言自身出位位置的前面,能匹配表达式 exp
- 示例:(?<=\bre)\w+\b,匹配以 re 开头的单词的后面部分;
- reading a book
- 匹配 ading
- 示例:(?<=\bre)\w+\b,匹配以 re 开头的单词的后面部分;
- 其他
- 断言用来声明一个应该为真的事实,正则表达式中只有断言的结果为真时,才会继续进行匹配;如果断言不为真,则匹配终止;
- (?<=\s)\d+(?=\s),匹配以空白字符间隔的数字;
- (?=exp),零宽度正预测先行断言,它断言自身出现位置的后面,能匹配表达式 exp
- 负向零宽断言(这个翻译真垃圾,或许应该叫:匹配不包含表达式指定的内容)
- (?!exp),断言此位置的后面不能匹配表达式 exp
- 示例:\d{3}(?!\d),匹配3个数字,且后面不能再跟着数字;
- 示例:\b((?!abc)\w)+\b,不包含连续字符串 abc 的单词;
- 与[^exp] 的区别:[^exp] 会消费一个字符进行判断,而 (?!exp) 不会
- (?<!exp),断言此位置的前面不能匹配表达式 exp
- 示例:(?<![a-z])\d{7},匹配不以小写字母开头的7位数字;
- 示例:(?<=<(\w+)>).*(?=<//1>),匹配不包含属性的简单 html 里面的内容;
- 不管是零宽断言,还是负向零宽断言,它都表示所断言的是其位置前后的情况,其本身不包含前后的内容;
- (?!exp),断言此位置的后面不能匹配表达式 exp
- 注释
- 语法:(?#注释内容)
- 示例:2[0-4]/d(?#200-249)|250-5|[01]?\d\d?(?#0-199)
- 建议启用选项"忽略模式里面的空白符,好处是:可以在注释中,随意添加空白符,例如空格、换行、TAB等,这些空白符都会被忽略不执行;
- 示例
- (?<= # 断言要匹配的文本的前缀)
- <(\w+)> # 查看尖括号括起来的字母或数字,即 html/xml 标签;
- ) # 前缀结束
- .* # 匹配任意文本
- (?= # 断言要匹配的文本的后缀)
- <//1> # 查找尖括号括起来的内容,其中前面一个字符是"/",后面是先前分组捕获的内容
- ) # 后缀结束
- 示例
- 语法:(?#注释内容)
- 贪婪与懒惰
- 正常情况默认是贪婪匹配,即能够满足条件下匹配尽可能多的字符;
- 懒惰匹配则是能满足条件下匹配尽可能少的字符;
- 示例
- a.*b,匹配以 a 开头,以 b 结尾的字符串,例如匹配 aabab,会得到整个字符串
- a.*?b,匹配以 a 开头, 以 b 结尾的字符串,但使用最少的重复,例如匹配 aabab,会得到 aab 和 ab 两个字符串
- 懒惰限定符
- *?,重复任意次,但尽可能少重复
- +?,重复1次或任意次,但尽可能少重复;
- ??,重复0次或1次,但尽可能少重复
- {n,m}?,重复 n-m 次,但尽可能少重复;
- {n,}?,重复 n 次以上,但尽可能少重复;
- 平衡组/递归匹配
- 思路:
- 从最左边开始,每找到一个左括号,将捕获的内容命名为 group,压入栈,直到将所有左括号找完;
- 每找到一个右括号,从栈中弹出一个组 group
- 如果堆栈上存在 group 的捕获内容,则执行匹配 yes 的表达式;如果不存在 group,则执行匹配 no 的表达式;
- 平衡组常用的一个应用是匹配 html 标签,例如嵌套的 标签
- 不同的语言/库可能不一定支持此功能,或者支持此功能但使用的语法可不同
- python 中 re 模块的一些处理函数
- re.match
- 作用:匹配字符,如果成功则返回 Match,如果失败则返回 None
- 示例:
- text = ‘John is a handsome boy, he is clever, cool, and so on.’
- m = re.match(r"(\w+)\s", text)
- 释义
- 函数原型:re.match(pattern, string, flags)
- 第一个函数是要匹配的内容,第二个是字符串,第三个控制参数,例如区分大小写、多行匹配等
- re.search
- re.sub
- re.split
- re.findall
- re.compile
正则表达式https://ccw1078.github.io/2017/04/04/正则表达式/
- 思路: