Upgrade to Pro — share decks privately, control downloads, hide ads and more …

正则表达式

shhhz
June 30, 2021

 正则表达式

正则表达式的基础、历史以及自动机理论简介。

shhhz

June 30, 2021
Tweet

More Decks by shhhz

Other Decks in Technology

Transcript

  1. 基本用法 匹配数字 \d ! [0-9] 匹配字母 [a-z] "#$% 匹配单字字符(字母、数字或下划线) \w

    ! [0-9a-zA-Z_] $name = ””; [A-Z] &#$% Regular expressions originated in 1951. Regular expressions originated in 1951. Regular expressions originated in 1951.
  2. 基本用法 限定符 {n} 正好 n 次 Regular expressions originated in

    1951. \d{4} {n,} 至少 n 次 Regular expressions originated in 1951. \w{10,} {n,m} 至少 n 次,至多 m 次 Regular expressions originated in 1951. \w{5,8} * 等价于 {0,} \d* ? 等价于 {0,1} \d? + 等价于 {1,} \d+
  3. 基本用法 标记 [..] 匹配方括号内任意字符。 [Aa]pple 匹配 Apple 或者 apple [^..]

    匹配不在方括号内任意字符。 1[^13579]0 匹配 100、120、140、1a0 等 [..] 很多字符在方括号内都会失去本来的意义 [?.+] 匹配问号、点号或加号
  4. 基本用法 分组 (..) 记住和这个模式匹配的匹配项(捕获分组) Tel number is 800-820-8820 \d{3}-(\d{3}-(\d{4})) $2:8820

    $1:820-8820 (?:..) 匹配但不保存匹配项(非捕获分组) 分支条件 | 在两个或多个项之间进行选择。 (apple|banana|orange) (\d)\1 \:i 反向引用 800-820-8820 \d{3}-(?:\d{3}-(\d{4})) $1:8820 从左往右第一个匹配结果, 可以使用 g 来指定全局捕获
  5. 有趣的例子 1)匹配日期 Jan xx (01-31 或 1-31) • [12][0-9] •

    3[01] • 0?[1-9] Jan (0?[1-9]|[12][0-9]|3[01]) Jan ([12][0-9]|3[01]|0?[1-9]) 1 01 2 02 3 03 4 04 5 05 7 07 8 08 9 09 6 06 11 12 13 14 15 17 18 19 16 21 22 23 24 25 27 28 29 26 10 20 31 30 Jan 31
  6. 有趣的例子 1 01 2 02 3 03 4 04 5

    05 7 07 8 08 9 09 6 06 11 12 13 14 15 17 18 19 16 21 22 23 24 25 27 28 29 26 10 20 31 30 1 01 2 02 3 03 4 04 5 05 7 07 8 08 9 09 6 06 11 12 13 14 15 17 18 19 16 21 22 23 24 25 27 28 29 26 10 20 31 30 Jan ([123]0|[012]?[1-9]|31) Jan (0[1-9]|[12][0-9]?|3[01]?|[4-9])
  7. 基本用法 位置 ^ 匹配开始的位置 $ 匹配结束的位置 环视 (?=) 肯定顺序环视 (?<=)

    肯定逆序环视 (?!) 否定顺序环视 (?<!) 否定逆序环视 ^\d+$ 2019 2019.1.1 (零宽正向先行断言)(positive lookahead) (lookaround) its me! find me, not me! me(?=,) (?<=find\s)me me(?!\!) (?<!(its|not)\s)me 顺序(先行) 逆序(后行) (零宽正向后行断言) (零宽负向先行断言) (零宽负向后行断言) (positive lookbehind) (negative lookahead) (negative lookbehind)
  8. 贪婪匹配 贪婪量词(匹配优先量词):{m,n}、?、*、+ • 匹配 { “name”: “Regex” } “.*” “[^”]*”

    • 匹配 <div>Regex</div> <div>[^<div>]*</div> 非贪婪量词(忽略优先量词):{m,n}?、??、*?、+? “.*?” <div>.*</div> <div>.*?</div> <div>Regex</div></div> <div>Hello<div>Regex</div></div>
  9. 禁止回溯 • 原子捕获分组(atomic capturing groups) a(bc|b)c a(?>bc|b)c abcc ✅ ✅

    abc ✅ ❌ 又叫固化分组。像贪婪量词一样,但是不会进行回溯 • 理解表达式匹配的运作过程,理解需求,重写正则 (?>group) === (?=(group))\1
  10. 正则表达式的历史 1950s Stephen Cole Kleene 建立了自动机模型,使用该模型来识别(接收)一个语言 1950s Chomsky 将语言形式地定义为由一个字母表的字母组成的一些串的集合 Chomsky

    将他本人的形式语言的研究成果和 Kleene 的自动机的研究成果结 合起来,不仅确定了文法和自动机分别从产生和识别角度定义语言,而且证 明了文法与自动机的等价性。诞生了形式语言与自动机理论。 1950s
  11. Ken Thompson 发表了 《Regular Expression Search Algorithm》,描述了一种正 则表达式编译器 正则表达式的历史 1968

    由此也诞生了 qed,后来成了 Unix 中 ed 编辑器的基础 g/Regular Expression/p( Global Regular Expression Print )命令 独立为 grep
  12. DFA( Deterministic Finite Automata ) • 没有 ε 转移 •

    对于同一状态和同一输入,只会有一个转移 (a|b)*abb NFA DFA
  13. McMaughton-Yamada-Thompson 算法 归纳规则 已有正则表达式 s 和 t 的 NFA 分别为

    N(s) 和 N(t),构造 N(r): 1)并 当 r = s|t,N(r) 为
  14. 中缀表达式转后缀表达式 a*·(b|c·d) a*bcd·|· 1. 如果遇到字母,将其输出。 2. 如果遇到左括号,将其入栈。 3. 如果遇到右括号,将栈元素弹出并输出直到遇到左括号为止。左括号只弹出不输出。 4.

    如果遇到限定符,依次弹出栈顶优先级大于或等于该限定符的限定符,然后将其入栈。 5. 如果读到了输入的末尾,则将栈中所有元素依次弹出。 优先级:并 | < 连接符 · < 闭包 *
  15. 后缀表达式转 NFA • 如果为字母 s,构建基本 NFA N(s),并将其入栈 • 如果为 |,弹出栈内两个元素

    N(s)、N(t),构建 N(r) 将其入 栈(r = s|t) • 如果为 ·,弹出栈内两个元素 N(s)、N(t),构建 N(r) 将其入栈 (r = st) • 如果为 *,弹出栈内一个元素 N(s),构建 N(r) 将其入栈(r = s*) a*bcd·|· N(a) N(a*) N(a*) N(b) N(a*) N(b) N(c) N(d) N(a*) N(b) N(c) N(a*) N(b) N(cd) N(a*) N(b|(cd)) N(a*(b|(cd)))
  16. 更更有趣的例子 例:如何判断一个二进制是不是 3 的整数倍? • 一位二进制为 1 时,余 1 •

    一位二进制为 0 时,余 0 • 往右添加 1,原数乘 2 加 1,余 0 变余 1,余 1 变余 0,余 2 变余 2 • 往右添加 0,原数乘 2,余 0 变余 0,余 1 变余 2,余 2 变余 1 ^1((10*1)|(01*0))*10*$