Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

正则表达式学习总结(三) #25

Open
Rashomon511 opened this issue Jul 26, 2019 · 0 comments
Open

正则表达式学习总结(三) #25

Rashomon511 opened this issue Jul 26, 2019 · 0 comments

Comments

@Rashomon511
Copy link
Owner

正则表达式回溯法原理

回溯的本质上就是深度优先搜索算法,从一初始状态开始匹配,若是匹配到尽头未遇到匹配失败,这种情况下不会发生回溯,但是尝试匹配失败时,接下来的一步就是后退一步或若干步,从 另一种可能“状态”出发,继续搜索,直到所有的“路径”(状态)都试探过,知道匹配成功,这一行为称为回溯。

贪婪量词

当多个贪婪量词挨着存在,并相互有冲突时,会尽可能多的匹配

var string = "12345";
  var regex = /(\d{1,3})(\d{1,3})/;
  console.log( string.match(regex) );
  // => ["12345", "123", "45", index: 0, input: "12345"]
// 前面匹配123,后面匹配45

惰性量词

惰性量词就是在贪婪量词后面加个问号。表示尽可能少的匹配

var string = "12345";
  var regex = /(\d{1,3}?)(\d{1,3})/;
  console.log( string.match(regex) );
  // => ["1234", "1", "234", index: 0, input: "12345"]
// 其中 \d{1,3}? 只匹配到一个字符 "1",而后面的 \d{1,3} 匹配了 "234"

分支结构

分支结构,可能前面的子模式会形成了局部匹配,如果接下来表达式整体不匹配时,仍会继续尝试剩下的分
支。这种尝试也可以看成一种回溯

var string = "candy";
  var regex = /can|candy/;
  console.log( string.match(regex) );
// ["can", index: 0, input: "candy", groups: undefined]

总结

  • 贪婪量词“试”的策略是:买衣服砍价。价钱太高了,便宜点,不行,再便宜点。
  • 惰性量词“试”的策略是:卖东西加价。给少了,再多给点行不,还有点少啊,再给点
  • 分支结构“试”的策略是:货比三家。这家不行,换一家吧,还不行,再换

正则表达式的拆分

正则表达式的结构包括字符字面量、字符组、量词、锚、分组、选择分支、反向引用的七种结构:

  • 字面量:匹配一个具体字符,包括不用转义的和需要转义的。比如 a 匹配字符 "a", 又比如 \n 匹配换行符,又比如 . 匹配小数点。
  • 字符组 :匹配一个字符,可以是多种可能之一,比如 [0-9],表示匹配一个数字。 也有 \d 的简写形式。 另外还有反义字符组,表示可以是除了特定字符之外任何一个字符,比如 [^0-9], 表示一个非数字字符,也有 \D 的简写形式。
  • 量词 :表示一个字符连续出现,比如 a{1,3} 表示 "a" 字符连续出现 3 次。 另外还有常见的简写形式,比如 a+ 表示 "a" 字符连续出现至少一次。
  • 锚:匹配一个位置,而不是字符。比如 ^ 匹配字符串的开头,又比如 \b 匹配单词边界, 又比如 (?=\d) 表示数字前面的位置。
  • 分组:用括号表示一个整体,比如 (ab)+,表示 "ab" 两个字符连续出现多次, 也可以使用非捕获分组 (?:ab)+。
  • 分支:多个子表达式多选一,比如 abc|bcd,表达式匹配 "abc" 或者 "bcd" 字符子串。 反向引用,比如 \2,表示引用第 2 个分组。

正则表达式的操作符都体现在结构中,即由特殊字符和普通字符所代表的一个个特殊整体,优先级如下:

  • 转义符: \ 优先级为1
  • 括号和方括号: (...)、(?:...)、(?=...)、(?!...)、[...] ,优先级为 2
  • 量词限定符: {m}、{m,n}、{m,}、?、*、+ ,优先级为3
  • 位置和序列: ^、$、\元字符、一般字符, 优先级为4
  • 管道符(竖杠): | ,优先级为5

注意要点

  • 匹配字符串整体问题:匹配整个字符串,我们经常会在正则前后中加上锚 ^ 和 $,由于优先级问题位置字符和字符序列优先级要比竖杠高。需要注意的是需要吧字符和竖杠用()括起来。
    例子:/^abc|bcd$/ => /^(abc|bcd)$/
  • 量词连缀问题:
    例子: /^[abc]{3}+$/ => /([abc]{3})+/
  • 元字符转义问题: 在 string 中, \ 字符也要转义的,也可以把每个字符转义,当然,转义后的结果仍是本身.但不是每个字符都需要转义。
    • 开头的 ^ 必须转义,不然 会把整个字符组,看成反义字符组
  • 匹配字符串 "{3,5}",只需要把正则写成 /{3,5}/,匹配字符串 "[abc]" ,可以写成 /[abc]/,也可以写成 /[abc]/
    • =、!、:、-、, 等符号,只要不在特殊结构中,并不需要转义

示例:
身份证:

let regex = /^(\d{15}|\d{17}[\dxX])$/

IPV4 地址:

let regex = /^((0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])\.){3}(0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])$/
@Rashomon511 Rashomon511 changed the title 正则表达式学习总结(三 正则表达式学习总结(三) Jul 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant