正则表达式--内功心法


    • 目的或意义
    • 概念
    • 应用场景
    • 正反向预查
    • 非贪婪模式 VS 贪婪模式
    • 执行过程
      • 递归
      • 回溯
    • 符号的运算优先级
    • 正则常用符号及含义
      • 普通字符
      • 非打印字符
      • 特殊字符
      • 限定符号
      • 字符簇

目的或意义 对字符串进行过滤筛选匹配,得到预期的值或效果
概念 对字符串和特殊符号操作的逻辑公式
应用场景 表单校验,条件搜索查询,数据替换等
正反向预查 预查是非捕获特性,javascript不支持反向预查
例如:


  • ?:

window(?:10|7) 可以匹配window10 或 window7
/window(?:10|7)/.test("window10")//true

`匹配过程是如何的呢?` 字符串从左到右,游标起始于字符串开始部分的左侧,正则表达式的w与字符串w匹配,匹配成功后,游标移动到w右侧,然后匹配i,匹配成功后,游标继续游走,以此类推直到游标停留到字符串末尾
  • ?=
    /window(?=7)/.test("window7") //true

    匹配过程又如何呢?
    游标由字符串的最左侧开始,正则表达式以此匹配直到window的右侧,此时游标停留,正则继续匹配,当匹配到7的时候,匹配成功。由于游标停留在7的左侧(即w的右侧),因此得到的匹配结果是window而不是window7
  • ?!
/window(?!7)/.test("windowXP")//true

此时的匹配过程又该如何
跟上面?=类似,不同的是XP与正则中的7不对应时为匹配成功
非贪婪模式 VS 贪婪模式
  • 贪婪模式
    例如:
/ab*c/.test("abbbc") //匹配abbbc

正则表达式--内功心法
文章图片

过程如下:
游标从a左侧开始,正则与字符串匹配到ab后,b继续与b*匹配,直到c与b*匹配,发现不能匹配,于是,选用备选路线,选用用字符串c与正则c匹配,匹配上游标前进到c的右侧全部匹配完成
  • 非贪婪模式
例如:
/ab*?c/.test("ac")//匹配ac

正则表达式--内功心法
文章图片

正则中? 是优先考虑的
过程如下:
游标从字符串”ac”中a的左侧开始,正则a与字符a匹配上,游标前进到a的右侧,此时模式中的”b*?” 与字符”c”匹配不上,于是,选用备用方案,正则会用”c” 与跟 字符串的”c”匹配,匹配上后,游标移动到末尾,因此匹配的值是ac
执行过程
基于PCRE的正则引擎有一个特点:递归和回溯
递归
/^c*?d(?=e)/.test("cde")//true, 匹配cd

  1. ^表示起始位置0(即字符串cd的左侧)
    $表示字符串末尾
  2. “cd”中的c与正则中的c*?进行匹配,游标继续前进,
  3. “cd”中的d与c*?匹配不上时,选用备选路线
  4. “cd”中的d与正则中的d对比并匹配上
  5. ?=e不占用位置但是要校验e值的存在(即游标在d右侧时,”cde”中e与?=e匹配上,游标不会移动)
类似?=e这种零位占用还有^,$
回溯
/tf??a/.test("tea")//false

过程如下:
1. 由字符串”tea”左侧开始,”tea” 的t 与 正则t匹配
2. 忽略f?? 直接匹配正则a,”tea”的”e” 与 正则表达式中”a” 对比,匹配失败
3. 正则表达式回溯到f??, 此时“tea”中的“e” 与正则表达式中“f??“对比,匹配失败
4. 正则模式继续回退,此时正则表达式中t与字符串中”e“比较,匹配失败
对于??,是可优先忽略的
符号的运算优先级
优先级从高到低
操作符号 描述
\ 转义符
(), (?:), (?=), [] 圆括号和方括号
*, +, ?, {n}, {n,}, {n,m} 限定符
^, $, \anymetacharacter 位置和顺序
| “或”操作
正则常用符号及含义 普通字符
非打印字符
字符 含义 备注
\f 换页符 等价于 \x0c 和 \cL
\cx 匹配由x指明的控制字符 \cM 匹配一个 Control-M 或回车符
\n 换行符 等价于 \x0a 和 \cJ
\r 匹配一个回车符。 等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。 等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。 等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。 等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。 等价于 \x0b 和 \cK。
特殊字符
字符 含义 备注
$ 匹配输入字符串的结尾位置。 如果设置了 RegExp 对象的 Multiline 属性,则也匹配‘\n′或‘\r′。要匹配也 匹 配 ‘ \n ′ 或 ‘ \r ′ 。 要 匹 配字符本身,请使用 \$。
( ) 标记一个子表达式的开始和结束位置。 子表达式可以获取供以后使用。要匹配这些字符,请使用 ( 和 )。
* 匹配前面的子表达式零次或多次。 要匹配 * 字符,请使用 *。
+ 匹配前面的子表达式一次或多次。 要匹配 + 字符,请使用 +。
. 匹配除换行符 \n之外的任何单字符。 要匹配 .,请使用 \。
[ 标记一个中括号表达式的开始。 要匹配 [,请使用 [。
? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。 要匹配 ? 字符,请使用 \?。
\ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。 例如, ‘n’ 匹配字符 ‘n’。’\n’ 匹配换行符。序列 ‘\’ 匹配 “\”,而 ‘(’ 则匹配 “(”。
^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。 要匹配 ^ 字符本身,请使用 \^。
{ 标记限定符表达式的开始。 要匹配 {,请使用 \{。
| 指明两项之间的一个选择。 要匹配 |,请使用 \|。
定位符号
用来描述字符串或单词的边界
^
字符串以何元素开始
$
字符串以什么结束
\b
描述单词以何为边界
\B
描述单词非边界情况
限定符号
字符 含义 备注
* 匹配前面的子表达式零次或多次。 * 等价于{0,}。
+ 匹配前面的子表达式一次或多次。 + 等价于 {1,}。
? 匹配前面的子表达式零次或一次。 ? 等价于 {0,1}。
{n} n 是一个非负整数。匹配确定的 n 次。 例如,’o{2}’ 不能匹配 “to” 中的 ‘o’,但是能匹配 “tooth” 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。 例如,’o{2,}’ 不能匹配 “to” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。’o{1,}’ 等价于 ‘o+’。’o{0,}’ 则等价于 ‘o*’。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。 例如,”o{1,3}” 将匹配 “fooooood” 中的前三个 o。’o{0,1}’ 等价于 ‘o?’。请注意在逗号和两个数之间不能有空格。
字符簇
字符 含义 备注
\d 匹配一个数字字符。 等价于 [0-9]。
\D 匹配一个非数字字符。 等价于 [^0-9]。
\w 匹配包括下划线的任何单词字符。 等价于’[A-Za-z0-9_]’。
\W 匹配任何非单词字符。 等价于 ‘[^A-Za-z0-9_]’。
\num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。 例如,’(.)\1′ 匹配两个连续的相同字符。
作者简介:
【正则表达式--内功心法】就职于甜橙金融信息技术部,负责前端开发工作,先后任职携程,平安等公司的前端开发工程师职位,喜欢研究新的技术,服务于业务需求,熟练运用Linux/Unix系统命令,以终端为载体,快速执行操作。

    推荐阅读