正则表达式
专门用于高级字符串匹配算法的 DSL。属于通用 DSL,几乎被所有的语言所内置支持,其理论到实际应用的发展,经历了半个多世纪的演变,从一种数学工具,逐步成为计算机科学中不可或缺的部分,极大地提高了文本处理和数据验证的效率。
正则表达式的原理涉及模式匹配(Pattern Match)和有限自动机(Finite Automaton, FA)理论。
模式匹配是指使用一定的语法来代表和描述一个字符串的特征。给定一个模式,并通过编译,形成一个有限自动机程序,然后使用该模式对目标字符串进行匹配。
模式语法
普通字符。26 个英文字母、10 数字、任意其他语言普通文字……
特殊字符。这些特殊的符号在正则表达式中拥有特殊含义,如果需要表达这些符号本身,那么需要加上一个
\
进行转义。.
:匹配任意单个字符。- 位置匹配。
^
匹配字符开头,$
匹配字符结尾。 - 分组捕获。
()
。标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。在 JS 中,在匹配结果数组中的 1 号索引开始的位置是子表达式的结果,如果没有分组,那么该值为空。 - 数量描述。
*
:匹配前一个字符或者分组 0 次或多次,+
:1 次或多次,?
:0 次或 1 次,{0,3}
:匹配一个字符 0 到 3 次,闭区间,只有一个数字就是匹配明确指明匹配几次,如{4}
;对应有这些字符匹配的非贪婪模式:*?
:非贪婪模式,尽可能少的匹配,+?
:非贪婪模式,尽可能少的匹配。 []
:拾取框。从拾取框中任选一个字符进行匹配,[^]
:反向拾取,从不在框中的字母中选一个进行匹配|
:或者,选择左右两个字符中的一个进行匹配。- 非捕获匹配。用于限制单词的边界。
- (?:<pattern>),匹配一个子表达式,但是不捕获匹配的文本
- (?=<pattern>),匹配前一个字符的位置,要求前面的紧挨着的这个位置的字符串能够匹配 pattern
- (?<=<pattern>),匹配前一个字符的位置,要求后面的紧挨着的这个位置的字符串能够匹配 pattern eg. (?<=abc).+(?=def),匹配任意以 abc 开头,def 结尾的字符串
- (?!<pattern>),匹配前一个字符的位置,要求前面的紧挨着的这个位置的字符串不能够匹配 pattern
- (?<!<pattern>),匹配前一个字符的位置,要求前面的紧挨着的这个位置的字符串不能够匹配 pattern
转义字符。
- \d:匹配数字
- \r:匹配回车键、\n:匹配换行符、\t:换行符、
:空格
- \s:匹配空白字符,包括空格、制表符、换页符等等
- \b:匹配单词边界。单词字母符号:字母(a-z,A-Z)、数字(0-9)和下划线(_)。\b 是一个非匹配字符,它不匹配实际的字符,但是匹配一个空位置,这个位置必须是两侧有一个是单词字母字符,另一个不是。
ps
不同操作系统使用不同的控制字符或组合来表示换行:
- Windows:使用回车和换行的组合 \r\n 来表示换行。
- Unix/Linux/macOS:使用换行 \n 来表示换行。
- 旧版 macOS(Mac OS 9 及以前):使用回车 \r 来表示换行。
带"<"的表示反向查找,就是以 xxx 为左边界,不带"<"的表示正向,以 xxx 为右边界,":"的为双向查找
常用例子
- 单词,
\w、\W(不匹配)、\b(单词边界)
- 空字符,
\s、\S
- 中文,
[\u4e00-\u9fa5]
- 小数,
(-?\d+)(\.\d+)?
- 邮箱,
\b[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,6}\b
- 边界,
(?:xxx).*(?:xxx)、(?<=xxx).*(?=xxx)、(?<!xxx).*(?!xxx)