正则表达式介绍

原文:An Introduction to Regular Expressions

作者:Tom Elliott

译者:kmyhy

正则表达式(也叫“正则式”)是一个用于表示某种模式的字符串或者字符序列。可以把它看成是搜索字符串——但是功能要强大得多!

在文本编辑器或字处理软件中能够进行纯文本搜索。正则表达式也能进行这种简单的搜索,更胜一筹的是,它还允许你搜索模式,比如 2 位数字 + 1 位字母,或者 3 个字母 + 1 个连字符号。

这种模式允许你实现一些有用的功能比如校验字段(电话号码、email 地址),检查用户输入,进行高级文本操作等等。

用底部的 download materials 按钮可以下载一个 Regular Expression Cheat Sheet pdf 文件和一个练习时使用到的 Swift playground 的文件。你可以将 Cheat Sheet 打印出来作为开发时的参考书。在 Swift playground 文件中包含了几个示例,可以用它来测试各种正则表达式。所有的正则表达式例子,无论是本教程中的还是后面一个教程的,在这个 playground 中都有现成的例子,你可以参考它们。

基本概念

如果你刚接触正则表达式,不知道它是干什么的,那么你可以看这个解释:正则表达式是一种搜索指定文本是否匹配某个模板的方法。关于正则表达式有大量精彩的书籍和教程——请参考本文最后的列表。

正则表达式的 Playground 脚本

在本教程中,我们会编写许多正则表达式。如果在编写它们的过程中能够直观地看到结果,那么用 Swift 写一个 Playground 脚本是一个绝佳的好办法!

在下载的 playground 文件的开头包含许多函数,用于将一段文本中的正则表达式搜索结果高亮出来,在 playground 的结果模板中显示匹配列表或分组列表,以及文本。现在无须关心这些方法是怎么实现的,你会在下一篇教程中学习它们。现在,跳到 Basic Examples and Cheat Sheet 部分,开始学习那些例子。

在 playground 的结果栏中,你会看到每个例子的匹配列表。对于高亮的例子,你可以将鼠标放在结果上面,点击眼睛或空心圆图标,就会高亮显示出匹配的文本。

正则表达式介绍

后面我们会学习如何来创建 NSRegularExpression,现在我们来使用以下这个 playground,感受一下各种正则表达式是如何工作的,并尝试编写自己的模板。

示例

让我们从几个简单的例子开始。

例如匹配单词 jump 的例子:

jump

这是最简单的正则表达式。你可以在 iOS 中通过 API 搜索文本字符串中是否匹配这个表达式——如果找到匹配,你就可以拿到它的位置或者替换成其它文本。

还有稍微复杂一点的例子,同时匹配单词 jump 和 jumps:

jump(s)?

这个例子中使用了特殊字符。括号可以创建分组,问号表示匹配前面的元素(即分组)0 次或 1 次。

真正复杂的例子来了。匹配一堆HTML开始/结束标签以及两者之间的内容:

<([a-z][a-z0-9])\b[^>]>(.*?)</\1>

哇,好复杂的样子。别担心,在接下来的教程中,你会学习这个表达式中所有的特殊字符,你最终会明白它的含义的!:]

如果你想深究上面的表达式,请参考下面的这个解释

注:在现实生活中,你不应该用正则表达式来解析 HTML。而应该使用标准的 XML 解析器。

整体概念

在继续学习之前,首先需要理解几个正则表达式的概念。

原义字符是最简单的正则表达式。它们类似于字处理器或文本编辑器中的查找功能。例如,查找单个字符的表达式 t 将查找所有出现字母 t 的地方,而表达式 jump 则会查找所有出现 jump 的地方。非常简单吧!

和编程语言一样,在正则表达式语法中也存在转义字符,比如:

[
( 和 )
\
*
+
?
{ 和 }
^
$
.
| (管道符)
/

这些字符表示高级模板匹配。如果你想搜索这些字符,你必须用反斜杆进行转义。例如,要搜索圆点 . 符号,要使用 . 而不是 .。

不同的环境,比如 Python、Perl、Java、C#、Ruby 等,它们对正则表达式的实现都会有细微差别。Swift 也不例外!

无论 O-C 还是 swift 都需要对常量字符串中的特殊字符进行转义(比如,加一个反斜杠 \)。而反斜杠自身也是一个特殊字符。因为正则表达式模板也是字符串,因此当使用字符串和 NSRegularExpression 时,你必须对字符串中的反斜杠进行转义。

因此在你的 Swift(或 O-C)代码中,标准的正则表达式 . 应该写成 \.。

总结一下:

  • “\.” 表示字符串:.
  • 正则表达式 . 匹配 . 字符。

**捕获(圆括号)**用于将模板进行分组。例如,3(pm|am)会匹配 “3 pm” 和 “3 am”。管道符(|)相当于或(OR) 。在正则表达式中可以有任意多的管道符。例如,(Tom|Dick|Harry) 可以匹配三个名字中的任意一个。

如果你需要指定某个字符串是可选的,可以使用圆括号进行分组。比如你想搜索字符串中的 “November”,但用户有可能会对这个月份使用简写 “Nov”,那么你可以使用模板 Nov(ember)?。即在圆括号后面加一个 ?号,表示圆括号中的内容是可选的。

我们将圆括号称作“捕获”是因为它会将匹配的内容捕获给你,让你正则式的其它地方引用它。

例如,假设有一个字符串 “Say hi to Harry”。如果that guy $1创建一个正则表达式去替换用 (Tom|Dick|Harry)搜索到的结果,则会将文字变成 “Say hi to that guy Harry”。$1 表示引用上一次处理中的第一个捕获组。

捕获和非捕获组稍微有点难。你会在后续教程中看到捕获和非捕获组的内容。

Character 类用于表示一个单个字符,它可能是一系列字符中的一个。Character 类一般出现在一对方括号之间。

例如,t[aeiou] 会匹配 “ta”, “te”, “ti”, “to”, 或 “tu”。在方括号中可以有任意多字符,但只会匹配其中一个。[aeiou] 包含 5 个字符,但要么是 a,要么是 e,要么是 i,要么是 o,或者是 u。

你可以在 Character 类中指定字符可能存在的范围。例如,如果要匹配一个从 100 到 109 之间的数字,你可以用 10[0-9]。这等同于 10[0123456789],但通过范围的指定,你的正则表达式显得更加清晰、易读。

Character 类不仅仅限于数字——也可以用于表示字母。例如,[a-f] 会匹配 a、b、c、d、e、f。

Character 类通常包含了你想匹配的字符,但如果你想让表达式不匹配某个字符怎么办?你可以定义一个否定的 Character 类,即使用 ^ 进行打头。例如,t[^o]表示匹配字母 t 和一个不是 o 的字符,即排除了单词 to。

NSRegularExpression 速查表

正则表达式很多时候语法都很简单,但也有一些极其复杂的例子!哪怕是最厉害的正则表达式专家,也需要有一个速查表,已应对那些棘手的问题。

在下载内容中包括了一个 pdf, 它是 ranwenderlich.com 官方提供的正则表达式速查表。

此外,这里罗列了一下速查表中的一些简单写法和对应解释:

  • . 匹配任意字符。p.p 匹配 pop、pup、pmp、[email protected] 等。
  • \w 匹配任意“单词类”的字符,包括数字、字母、下划线,但不包括标点符号或其他符号。hello\w 匹配 hello_、hello9、helloo,但不匹配 hello!
  • \d 匹配一位数字,也就是 [0-9]。\d\d?:\d\d 匹配时间字符串,比如 9:00 和 12:45。
  • \b 匹配单词分隔符,比如空格和标点符号。to\b 匹配 “to the moon” 中的 “to” 和 “to!”,但不匹配 “tommorrow”。\b 可用于整词匹配。
  • \s 匹配空白字符,比如空格、tab、换行符。hello\s 匹配字符串 “Well, hello there!” 中的 “hello”。
  • ^ 匹配一行的开始。注意这个 ^ 和方括号中的 ^ 是不一样的!例如,^Hello 匹配 “Hello there”,但不匹配 “He said Hello”。
  • $ 匹配行末。例如,end$ 匹配 “It was the end” 但不匹配 “the end was near”。
  • * 匹配前一个元素 0 次或多次。12*3 匹配 13、123、1223、122223、1222222223.
  • + 匹配前一个元素 1 次或多次。12+3 匹配 123、1223、122223、1222222223,但不匹配 13。
  • 花括号 {} 中包含一个最小匹配次数和一个最大匹配次数。例如,10{1,2}1 匹配 101、1001,但不匹配 10001,因为最小次数是 1,最大次数是 2。He[Ll]{2,}o 会匹配 “HeLLo” 和 “HellLLLllo” 以及 “hello” 中有人一个 L 的变体,因为最小数是 2,最大数缺失——这表示不限次数。

作为初学,这就足够了。

这时应该自动动手实验下这些例子,它们全都在上面所提的 playground 中包含了。

接下来去哪?

关于正则表达式,下面罗列了一些有用的链接:

  • www.regular-expressions.info 是 Jan Goyvaerts 的主页。他也出版了基本关于正则表达式的全面
  • NSRegularExpression 类参考是 NSRegularExpression API 的重要参考。
  • 要快速测试正则表达式模板,可以使用 regexpal.com

一定要下载“正则表达式速查 pdf”和练习用的 playground,下载按钮在最后。

请到我们的 NSRegularExpression 教程 中看看如何在 Swift 中使用正则表达式!:]

Download Materials