Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
正则表达式
Search
shhhz
June 30, 2021
Technology
0
29
正则表达式
正则表达式的基础、历史以及自动机理论简介。
shhhz
June 30, 2021
Tweet
Share
More Decks by shhhz
See All by shhhz
概率与随机
shhhz
0
37
游戏中的奥秘
shhhz
0
41
Seam Carving 算法
shhhz
0
220
Other Decks in Technology
See All in Technology
Android 15 でウィジェットピッカーのプレビュー画像をGlanceで魅せたい/nikkei-tech-talk-27-1
nikkei_engineer_recruiting
0
100
組織成長を加速させるオンボーディングの取り組み
sudoakiy
3
340
心が動くエンジニアリング ── 私が夢中になる理由
16bitidol
0
130
Python(PYNQ)がテーマのAMD主催のFPGAコンテストに参加してきた
iotengineer22
0
600
SkiaとImpellerについて
moriya0130
0
170
Amazon Forecast亡き今、我々がマネージドサービスに頼らず時系列予測を実行する方法
sadynitro
0
190
Platform Engineering for Software Developers and Architects
syntasso
1
620
【Pycon mini 東海 2024】Google Colaboratoryで試すVLM
kazuhitotakahashi
2
630
【Startup CTO of the Year 2024 / Audience Award】アセンド取締役CTO 丹羽健
niwatakeru
0
2k
DynamoDB でスロットリングが発生したとき/when_throttling_occurs_in_dynamodb_short
emiki
0
310
Adopting Jetpack Compose in Your Existing Project - GDG DevFest Bangkok 2024
akexorcist
0
130
Why App Signing Matters for Your Android Apps - Android Bangkok Conference 2024
akexorcist
0
140
Featured
See All Featured
A better future with KSS
kneath
238
17k
Product Roadmaps are Hard
iamctodd
PRO
49
11k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
Designing the Hi-DPI Web
ddemaree
280
34k
Raft: Consensus for Rubyists
vanstee
136
6.6k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
16
2.1k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
365
24k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
26
2.1k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
31
2.7k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
250
21k
What's new in Ruby 2.0
geeforr
343
31k
Transcript
{正则表达式} @孙恒哲
使用 历史 自动机
正则表达式的使用
使用场景 正则表达式赋予使用者描述和分析文本的能力。 文本处理 • 查找文本(区分大小写、符合特定位置) • 提取文本(邮件中的字段) • 替换文本(金融货币)
基本用法 匹配数字 \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.
基本用法 匹配任意字符(除换行符) . 匹配空白字符(空格、制表符、换页符和换行符) \s Regular expressions originated in 1951.
基本用法 限定符 {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+
基本用法 标记 [..] 匹配方括号内任意字符。 [Aa]pple 匹配 Apple 或者 apple [^..]
匹配不在方括号内任意字符。 1[^13579]0 匹配 100、120、140、1a0 等 [..] 很多字符在方括号内都会失去本来的意义 [?.+] 匹配问号、点号或加号
基本用法 分组 (..) 记住和这个模式匹配的匹配项(捕获分组) 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 来指定全局捕获
有趣的例子 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
有趣的例子 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])
有趣的例子 2)判断一个数是否是合数(非质数) ^.?$|^(..+?)\1+$ 3)判断 11x + 2y + 5z =
115 是否有自然数解 ^(.*)\1{10}(.*)\2{1}(.*)\3{4}$
基本用法 位置 ^ 匹配开始的位置 $ 匹配结束的位置 环视 (?=) 肯定顺序环视 (?<=)
肯定逆序环视 (?!) 否定顺序环视 (?<!) 否定逆序环视 ^\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)
更有趣的例子 例:金融货币格式化 需求:每隔三位添加一个逗号 1234567 -> 1,234,567 1 234 567 3n
(?<= ) (?= ) $ \d+ (\d{3})+
贪婪匹配 贪婪量词(匹配优先量词):{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>
回溯 正则:ab{1,3}bbc 文本:abbbc 原因:NFA 引擎的实现方式
回溯 正则:^(\d+)*$ 文本:123456789! 123456789 12345678 9 1234567 89 1234567 8
9 正则:^(\d+?)*$ \d+ (\d+)*
禁止回溯 • 原子捕获分组(atomic capturing groups) a(bc|b)c a(?>bc|b)c abcc ✅ ✅
abc ✅ ❌ 又叫固化分组。像贪婪量词一样,但是不会进行回溯 • 理解表达式匹配的运作过程,理解需求,重写正则 (?>group) === (?=(group))\1
正则表达式的历史
Warren McCulloch与 Walter Pitts 将神经系统中的神经元描述成小而简单的自动控制元。 正则表达式的历史 1940s
正则表达式的历史 1950s Stephen Cole Kleene 建立了自动机模型,使用该模型来识别(接收)一个语言 1950s Chomsky 将语言形式地定义为由一个字母表的字母组成的一些串的集合 Chomsky
将他本人的形式语言的研究成果和 Kleene 的自动机的研究成果结 合起来,不仅确定了文法和自动机分别从产生和识别角度定义语言,而且证 明了文法与自动机的等价性。诞生了形式语言与自动机理论。 1950s
Ken Thompson 发表了 《Regular Expression Search Algorithm》,描述了一种正 则表达式编译器 正则表达式的历史 1968
由此也诞生了 qed,后来成了 Unix 中 ed 编辑器的基础 g/Regular Expression/p( Global Regular Expression Print )命令 独立为 grep
正则表达式与自动机
形式语言与自动机 形式语言 自动机 正则表达式的核心是有穷自动机
• 一个初始状态 NFA( Nondeterministic Finite Automata ) • 一个或多个终结状态 •
状态转移函数 (a|b)*abb a
ε-NFA 除了能到达多个状态之外,NFA 还能接受空符号 ε (a+|b+)
DFA( Deterministic Finite Automata ) • 没有 ε 转移 •
对于同一状态和同一输入,只会有一个转移 (a|b)*abb NFA DFA
McMaughton-Yamada-Thompson 算法 McMaughton-Yamada-Thompson 算法可以将任何正则表达式转变为接受相同语言的 NFA。它分为两个规则: 基本规则 1)对于表达式 ε,构造下面的 NFA: 2)对于非
ε,构造下面的 NFA:
McMaughton-Yamada-Thompson 算法 归纳规则 已有正则表达式 s 和 t 的 NFA 分别为
N(s) 和 N(t),构造 N(r): 1)并 当 r = s|t,N(r) 为
McMaughton-Yamada-Thompson 算法 2)连接 当 r = st,N(r) 为 3)闭包 当
r = s*,N(r) 为
正则表达式转自动机 a*(b|cd) * · b · c d | a
中缀表达式转后缀表达式 a*·(b|c·d) a*bcd·|· 1. 如果遇到字母,将其输出。 2. 如果遇到左括号,将其入栈。 3. 如果遇到右括号,将栈元素弹出并输出直到遇到左括号为止。左括号只弹出不输出。 4.
如果遇到限定符,依次弹出栈顶优先级大于或等于该限定符的限定符,然后将其入栈。 5. 如果读到了输入的末尾,则将栈中所有元素依次弹出。 优先级:并 | < 连接符 · < 闭包 *
后缀表达式转 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)))
NFA 转 DFA 子集构造法算法可以将 NFA 转变为等价的 DFA。 NFA DFA
更更有趣的例子 例:如何判断一个二进制是不是 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*$
推荐网站 正则表达式可视化 https://regexper.com https://regex101.com/ 在线运行、调试、分析
THANK YOU!