分钟学会正则表达式(译)

正则表达式(“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”。

在一段文本中,这个表达式将会找到catcotczt,甚至字面值为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”。在一段文本中,将会匹配到catcetcitcotcut
  • 正则表达式[0123456789]表示找到一个数字
  • 正则表达式[a]a意义相同:“找到a

一些转义的例子:

  • [a]表示“找到一个左方括号紧跟着一个a,再跟着一个右方括号”。
  • [[]ab]表示“匹配一个左方括号或者右方括号或者a或者b”。
  • [[]]表示“匹配一个反斜杆或者一个左方括号或者一个右方括号”。(呕!)

在字符类中顺序和重复字符并不重要。[dabaaabcc][abcd]一样。

重要的提示

在字符类内部的“规则”和在字符类内部的规则有所不同。一些字符在字符类内部扮演着元字符的角色,但在字符类外部则充当字面值。还有一些字符做着相反的事。一些字符在两种情形都为元字符,但在各自情形里代表不同的含义。

特别地,.表示“匹配任意字符”,但是[.]表示“匹配句点”。不能并为一谈。

练习

结合目前所学,在字典中,使用正则表达式查找有连续的元音和连续的辅音的单词。

字符类区间(ranges)

你可以在字符类中使用连字符来表示一个字母或数字的区间

  • [b-f][bcdef]都表示“找到一个bcdef”。
  • [A-Z][ABCDEFGHIJKLMNOPQRSTUVWXYZ]都表示“匹配大写字母”。
  • [1-9][123456789]都表示“匹配一个非零数字”。

连字符在字符类外部使用时并没有特别都含义。正则表达式a-z表示“找到一个a接着跟着一个连字符,然后匹配一个z”。

区间和单独的字符可能会共存于吥

原文发布于微信公众号 - php(phpdaily)

原文发表时间:2015-10-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏章鱼的慢慢技术路

2015年第六届蓝桥杯C/C++B组省赛题目解析

1762
来自专栏C语言及其他语言

[每日一题]破解平方数

这次的题目是九月月赛的第二题,相信大家肯定是没问题的 题目描述 给出m个数b1, b2,..., bm,每个数的素数因子都在前t个素数之内,任务是寻找这...

3196
来自专栏企鹅号快讯

Bash 脚本:正则表达式基础篇

正则表达式(简写为 regex 或者 regexp)基本上是定义一种搜索模式的字符串,可以被用来执行“搜索”或者“搜索并替换”操作,也可以被用来验证像密码策略等...

1768
来自专栏小樱的经验随笔

Vijos P1448 校门外的树【多解,线段树,树状数组,括号序列法+暴力优化】

校门外的树 描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段...

3327
来自专栏bboysoul

1468: C语言实验题――求级数值

输入:无 输出:级数的值,以float浮点数输出。 样例输入: 样例输出: 提示:输出格式:printf(“%f”,sum); 考点:公式的理解...

681
来自专栏抠抠空间

Python的编码问题(一)

一、什么是编码   可以说,计算机是一个即聪明又笨蛋的家伙。说它聪明,是因为他可以做很多事情,它的强大无需多说,大家应该都有所了解以及感受。但是为什么说它又是个...

3617
来自专栏互联网大杂烩

String.hashcode 源码分析

接触编程这么久了,一直会遇到某些高频词,例如,哈希。hashtable,hashmap,hashset等等等。都有hash一次。那什么是哈希值呢?百度本科解释是...

684
来自专栏应兆康的专栏

数据库相关专业术语

一、概念模型中相关术语 实体:客观存在并可以相互区分的事物叫实体。 实体型:具有相同属性的实体具有相同的特征和性质,用实体名及其属性名集合来抽象和刻画同类实体,...

2788
来自专栏偏前端工程师的驿站

JS魔法堂:彻底理解0.1 + 0.2 === 0.30000000000000004的背后

Brief                                 一天有个朋友问我“JS中计算0.7 * 180怎么会等于125.9999999999...

2036
来自专栏xingoo, 一个梦想做发明家的程序员

剑指OFFER之最大子向量和(连续子数组的最大和)(九度OJ1372)

题目描述: HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天JOBDU测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和...

17810

扫码关注云+社区