分钟学会正则表达式(译)
正则表达式(“regexes”)即增强查找/字符串替换操作。当在文本编辑器中编辑文字时,正则表达式经常用于:
- 检查文本是否包含一个给定的模式
- 查找任何匹配的模式
- 从文本中拉取信息(比如截断)
- 修改文本
和文本编辑器一样,绝大多数高级编程语言支持正则表达式。在本文中,“文本”仅仅是一个字符串变量,但是有效的操作却是一致的。某些编程语言(Perl,JavaScript)甚至为正则表达式提供专用的语法。
但是正则表达式是什么?
一个正则表达式仅仅为一个字符串。它没有长度限制,但是通常该字符串很短。下面看几个例子:
I had a S+ day today
[A-Za-z0-9-_]{3,16}
dddd-dd-dd
v(d+)(.d+)*
TotalMessages="(.*?)"
<[^<>]>
这个字符串实际上是一个极小的计算程序,并且正则表达式是一门语法小而简洁,领域特定的编程语言。牢记以下几点,它们不该在学习过程中让你感到惊讶:
- 每个正则表达式都能分解成一串指令。“找到这个,再找到那个,然后找到其中一个...”
- 一个正则表达式拥有输入(文本)和输出(模式匹配,和有些时候的自定义文本)。
- 存在语法错误——不是每个字符串都是合法的正则表达式!
- 语法有些怪异,也可以说是恐怖。
- 一个正则表达式有时候可以被编译以便更快运行。
正则实现一直有着显著的改变。对于本文,我所关注的是那些几乎每个正则表达式都实现了的核心语法。
练习
获取一个支持正则的文本编辑器。我推荐Notepad++。
下载一篇很长的散文故事比如Gutenberg出版社出版的H. G. Wells的《时光机器》然后打开它。
下载一部字典,比如这个,解压然后打开。
一切准备就绪,稍后开始练习。
提示:正则表达式与文件通配符语法完全不兼容,比如*.xml
。
正则表达式基础语法
字面值(Literals)
正则表达式由只代表自身的字面值和代表特定含义的元字符组成。
这里也有一些例子。我会对元字符进行高亮。
I had aS+day today
[A-Za-z0-9-_]{3,16}
dddd-dd-dd
v(d+)(.d+)*
TotalMessages="(.*?)"
<[^<>]*>
大部分字符,包括字母数字字符,会以字面值的形式出现。这意味着它们查找的是自身。比如,正则表达式cat
代表“先找到c
,接着找到a
,最后找到t
”。
目前为止感觉良好。这的确很像
- 一个普通的查找对话框
- Java中的
String.indexOf()
函数 - PHP中的
strpos()
函数 - 等等
提示:除非特别说明,正则表达式是区分大小写的。然而,绝大多数实现都会提供一个标记来开启不区分大小写的功能。
句点(dot)
我们第一个元字符是句号(译者注:句点,英文句号),.
。一个.
表示匹配任何单个字符。下面这个正则表达式c.t
代表“先找到c
,接着找到任何单个字符,再找到t
”。
在一段文本中,这个表达式将会找到cat
,cot
,czt
,甚至字面值为c.t
的字符串(c
,句点,t
),但是不包括ct
或者coot
。
在正则表达式里,空格是有效的。正则表达式 'c t' 代表”先找到 'c',接着找到空格,再找到 't'“。
任何元字符如果用一个反斜杆进行转义就会变成字面值。所以上述的正则表达式c.t
就代表“先找到c
,接着找到句号,再找到t
”。
反斜杠是一个元字符,这意味着它也可以使用反斜杠转义。所以正则表达式ct
代表“先找到c
,接着找到反斜杆,再找到t
”。
注意!在一些实现中,.
会匹配除了换行符的任意字符。这意味着“换行符”在不同的实现中也会变化。 要查看你的文档。在这篇文章中, 我会确保.
会匹配任意字符。
在其它情况下, 通常会有一个标记来调整这种行为,那就是`DOTALL`或类似的标记
练习
使用你目前所学,在字典中使用正则表达式,匹配一个有两个z
的单词,其中这两个z
离得越远越好。
练习
在《时光机器》这本书中,使用正则表达式来查找以介词收尾的句子。
字符类(Character classes)
字符类是字符在方括号中的集合。表示“找到集合里任意一个字符”。
- 正则表达式
c[aeiou]t
表示“找到c
后跟一个元音字母,再找到t
”。在一段文本中,将会匹配到cat
,cet
,cit
,cot
和cut
。 - 正则表达式
[0123456789]
表示找到一个数字 - 正则表达式
[a]
和a
意义相同:“找到a
”
一些转义的例子:
-
[a]
表示“找到一个左方括号紧跟着一个a
,再跟着一个右方括号”。 -
[[]ab]
表示“匹配一个左方括号或者右方括号或者a
或者b
”。 -
[[]]
表示“匹配一个反斜杆或者一个左方括号或者一个右方括号”。(呕!)
在字符类中顺序和重复字符并不重要。[dabaaabcc]
跟[abcd]
一样。
重要的提示
在字符类内部的“规则”和在字符类内部的规则有所不同。一些字符在字符类内部扮演着元字符的角色,但在字符类外部则充当字面值。还有一些字符做着相反的事。一些字符在两种情形都为元字符,但在各自情形里代表不同的含义。
特别地,.
表示“匹配任意字符”,但是[.]
表示“匹配句点”。不能并为一谈。
练习
结合目前所学,在字典中,使用正则表达式查找有连续的元音和连续的辅音的单词。
字符类区间(ranges)
你可以在字符类中使用连字符来表示一个字母或数字的区间:
-
[b-f]
和[bcdef]
都表示“找到一个b
或c
或d
或e
或f
”。 -
[A-Z]
和[ABCDEFGHIJKLMNOPQRSTUVWXYZ]
都表示“匹配大写字母”。 -
[1-9]
和[123456789]
都表示“匹配一个非零数字”。
连字符在字符类外部使用时并没有特别都含义。正则表达式a-z
表示“找到一个a
接着跟着一个连字符,然后匹配一个z
”。
区间和单独的字符可能会共存于吥
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python 爬取王者农药全套皮肤
- 时间都去哪儿了--python性能优化
- Python干货 | 遥感影像拼接
- Java8 Stream 创建流
- Java8 Stream 基本类型特化流
- Java8 Stream 自定义收集器Collector
- 收藏|Flink比Spark好在哪?
- SpringCloud Config 分布式配置
- 经过一年的煎熬,我们还是决定把系统升级成基于 Spring Cloud 的微服务架构
- OpenCV:人脸检测。
- 如何设计缓存系统:缓存穿透,缓存击穿,缓存雪崩解决方案分析
- OpenCV:图像检索。
- Zuul路由网关
- OpenCV:模板匹配。
- 【Vulnhub】pipe