怎样在Swift中使用正则表达式

栏目: Swift · 发布时间: 7年前

内容简介:正则表达式(Regular expression, regex)允许我们在几秒钟内在成千上万文档间进行复杂检索与替换,自从诞生50多年来它依旧广泛使用。在这篇文章中,我会讲解在Swift中正则表达式的基本用法。我们会从易到难,详细讲解一些最重要的正则表达式语法,以及一些有用的扩展。NSRegularExpression类让我们可以用正则表达式查找替换子字符串,它可以简洁灵活地描述文本。例如,如果你想从"My name is Taylor Swift"中提取出"Taylor Swift",可以写一个匹配文本

正则表达式(Regular expression, regex)允许我们在几秒钟内在成千上万文档间进行复杂检索与替换,自从诞生50多年来它依旧广泛使用。

在这篇文章中,我会讲解在Swift中正则表达式的基本用法。我们会从易到难,详细讲解一些最重要的正则表达式语法,以及一些有用的扩展。

NSRegularExpression:如何在字符串中匹配正则表达式

NSRegularExpression类让我们可以用正则表达式查找替换子字符串,它可以简洁灵活地描述文本。例如,如果你想从"My name is Taylor Swift"中提取出"Taylor Swift",可以写一个匹配文本“My name is”的正则表达式,它的后面可以是任何文本,之后把它传递给NSRegularExpression类。

具体可见下面代码。注意我们要提取出的是第二范围,因为第一范围是匹配的字符串,而第二范围才是"Taylor Swift"部分。

do {
    let input = "My name is Taylor Swift"
    let regex = try NSRegularExpression(pattern: "My name is (.*)", options: NSRegularExpression.Options.caseInsensitive)
    let matches = regex.matches(in: input, options: [], range: NSRange(location: 0, length: input.utf16.count))

    if let match = matches.first {
        let range = match.range(at:1)
        if let swiftRange = Range(range, in: input) {
            let name = input[swiftRange]
        }
    }
} catch {
    // regex was bad!
}

正则表达式的详细讲解

让我们从几个简单例子开始,方便不熟悉的人了解正则表达式。正则表达式,简称regex,用于让我们在字符串中进行模糊检索。例如我们知道”cat”包含”at”,但如果我们检索所有以“at”结尾的3字母单词该怎么做呢?

正则表达式就用于解决这个问题,尽管由于Objective-C的基础,它们的语法有些不太灵巧。

1. 首先,定义你想检索的字符串:

let testString = "hat"

之后创建NSRange实例来表示整个字符串的长度

let range = NSRange(location: 0, length: testString.utf16.count)

这里使用utf16来避免类似表情符号等带来的问题

2. 之后使用正则表达式语法创建NSRegularExpression实例

let regex = try! NSRegularExpression(pattern: "[a-z]at")

[a-z]在正则表达式中用于指定a到z之间任意字母。实际使用中你可能会提供一个无效的正则表达式,但是这里我们有了一个硬编码的正确正则表达式,所以就不需要查找错误了。

3. 最后在创建好的正则表达式调用firstMatch(in:),输入要检索的字符串,一些特殊选项,和字符串的范围。如果字符串匹配正则表达式,就会返回数据,否则就是nil。所以如果你想检查字符串是否完全匹配,就用firstMatch(in:)的结果和nil比较:

regex.firstMatch(in: testString, options: [], range: range) != nil

这里必须要用到NSRange——尽管这个API是为NSString设计,和Swift衔接的不太好。Swift String Manifesto可能会替换它,但看起来还要很久。

正则表达式“[a-z]at”会成功匹配“hat”,和“cat”, “sat”, “mat”, “bat”等等——我们只要关注想匹配什么,NSRegularExpression会处理好它。

让NSRegularExpression用起来更简单

接下里会展示更多的正则表达式语法,首先来看看如何让NSRegularExpression稍微好用一些

现在我们的要3行Swift代码来匹配一个简单字符串

let range = NSRange(location: 0, length: testString.utf16.count)
let regex = try! NSRegularExpression(pattern: "[a-z]at")
regex.firstMatch(in: testString, options: [], range: range) != nil

我们可以从多种方式改进,不过最有效的是扩展NSRegularExpression,让创建和匹配表达式更简单。

首先第一行:

let regex = try! NSRegularExpression(pattern: "[a-z]at")

我提到过,创建一个NSRegularExpression实例可能导致错误,因为可能会提供一个非法的正则表达式。比如[a-zat,忘记了]

结果就是,通常会用try!创建NSRegularExpression实例。然而这会导致lint工具(如SwiftLint)的破坏。所以好一点的方法是创建一个方便的初始化,能正确创建正则表达式,或者在开发时能生成一个断言失败。

extension NSRegularExpression {
    convenience init(_ pattern: String) {
        do {
            try self.init(pattern: pattern)
        } catch {
            preconditionFailure("Illegal regular expression: \(pattern).")
        }
    }
}

注意:如果你的app需要用户写正则表达式,你需要使用NSRegularExpression(pattern:)初始化,这样可以更好的处理错误。

之后这些行:

let range = NSRange(location: 0, length: testString.utf16.count)
regex.firstMatch(in: testString, options: [], range: range) != nil

第一行创建了一个包含整个字符串的NSRange,第二行则是在文本中查找first match。但这是很笨的方法,因为大多时候你想查找输入的整个字符串,用firstMatch(in:)与nil判定会弄混你的意图。

所以,用另一个扩展来替代它,它把下面代码包含在一个简单的matches()方法中。

extension NSRegularExpression {
    func matches(_ string: String) -> Bool {
        let range = NSRange(location: 0, length: string.utf16.count)
        return firstMatch(in: string, options: [], range: range) != nil
    }
} 

如果你把这两个扩展合并,就可以更轻松的创建和检索正则表达式了。

let regex = NSRegularExpression("[a-z]at")
regex.matches("hat") 

我们可以进一步通过运算符重载让Swift包含的,~=,运算符适用于正则表达式:

extension String {
    static func ~= (lhs: String, rhs: String) -> Bool {
        guard let regex = try? NSRegularExpression(pattern: rhs) else { return false }
        let range = NSRange(location: 0, length: lhs.utf16.count)
        return regex.firstMatch(in: lhs, options: [], range: range) != nil
    }
}

通过上面代码,我们可以在一句话的左边使用任意字符,右边用正则表达式。

"hat" ~= "[a-z]at"

注意:创建NSRegularExpression实例会有一定消耗,所以如果你想要反复使用一个正则表达式,最好把NSRegularExpression实例保存起来。

正则表达式语法学之旅

我们已经使用了[a-z]来表示“a”到“z”之间任意字母,在正则表达式中这是一个字符类。它让你指定要匹配的一组字母,可以通过制定的字母列表匹配,或者通过一段字符范围匹配。

正则表达式范围不一定是整个字母表,你可以用[a-t] 来排除“u”到“z”之间的字母。另外,如果你想特别指定一些字母,只需要像这样单独列出它们:

[csm]at

正则表达式默认区分大小姐写,也就是说“Cat”和“Mat”不会在“[a-z]at”被匹配。如果你想忽略大小写,可以使用“[a-zA-Z]at”,或者创建你自己的NSRegularExpression对象,并标记.caseInsensitive

除了大小写以外,你可以通过字符类指定数字范围。最常用的是[0-9]表示任何数字,或[A-Za-z0-9]表示任何字母数字混编字符,也可以用[A-Fa-f0-9]来表示16进制数字。

如果你想匹配一个字符序列,还需要一个叫做量词(quantifier)的概念。它用于表示字符出现的数量。

最常用的是星号量词,*,意思是匹配0个或更多。量词在它们修饰的字符后出现,就像下面这样:

let regex = NSRegularExpression("ca[a-z]*d")

这句话先查找“ca”,之后是0或多个从“a”到“z”的字母,最后是“d”——它能匹配“cad”, “card”, “clamped”等等。

除了*之外,还有2个类似的量词 + 和 ? 。 + 意味着“1个或更多”,与 * 的“0个或更多”有点区别。而 ? 的意思是”0或1个”

这些量词是正则表达式基础内容,希望大家能确实理解它们的区别,比如下面3个正则表达式

  1. ca[a-z]*d

  2. ca[a-z]+d

  3. ca[a-z]?d

并想想如果给出字符串“cd”或“clamped”,哪些能够匹配。

如果需要,可以用大括号 { 和 } 来更详细的指定匹配数量,比如[a-z]{3}意味着匹配3个小写字母。

考虑一个电话号码格式比如111-1111。如果要正好匹配这个格式,用[0-9-]+是行不通的。所以我们需要用这样的正则表达式[0-9]{3}-[0-9]{4},即先是3个数字,之后连接号,之后4个数字。

此外还可以用大括号指定范围,它可以是有界限的或无界限的。比如[a-z]{1,3}代表匹配1,2,或3个小写字母。[a-z]{3,}代表匹配3个或更多个

最后,元字符(meta-characters)是特殊字符,正则表达式中有特别的意义,在这里介绍其中几个使用最频繁的。

首先其中是最常用,也是最滥用的 . 字符。它可以匹配除了换行符以外任意一个字符。比如正则表达式c.t可以匹配“cat”,但不能匹配“cart”。如果你把 . 和 * 量词共同使用,就意味着匹配1个或多个除了换行符以外所有字符,这可能是你最常见的正则表达式了。

.* 常用的原因也显而易见:不需要具体设计一个特别的正则表达式,.* 就可以匹配几乎一切了。然而问题是,特定化本来就是正则表达式的要点之一,你可以在文本中精确查找一些字符并操作它们。而太多人完全依赖 .* ,却没有意识到这可能会给他们的表达式带来难以察觉的错误。

用前面电话号码的例子来说,我们用[0-9]{3}-[0-9]{4}匹配类似555-5555的电话号码。考虑到有些人会写成“555 5555”或“5555555”,我们可能就会把正则表达式条件放宽一些,改成[0-9]{3}.*[0-9]{4}

但是这样就带来一个问题,它会匹配“123-4567”, “123-4567890”, 或 “123-456-789012345”。为了让[0-9]{3}与[0-9]{4}匹配上,.* 会匹配尽可能多的字符

所以这里要用字符类与量词,比如[0-9]{3}[ -]*[0-9]{4},代表3个数字,之后0个或更多空格与连接线,之后4个数字。或者使用不包含字符类,即用它来匹配数字以外的字符,如[0-9]{3}[^0-9]+[0-9]{4},会匹配空格,连接线,斜杠等等,而不会匹配数字。

作者:Paul Hudson

链接:https://www.hackingwithswift.com/articles/108/how-to-use-regular-expressions-in-swift

翻译:cocoachina


以上所述就是小编给大家介绍的《怎样在Swift中使用正则表达式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Landing Page Optimization

Landing Page Optimization

Tim Ash / Wiley Publishing / 2008-1-29 / USD 29.99

在线阅读本书 How much money are you losing because of poor landing page design? In this comprehensive, step-by-step guide, you’ll learn all the skills necessary to dramatically improve your bottom li......一起来看看 《Landing Page Optimization》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

MD5 加密
MD5 加密

MD5 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器