iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >Swift 中的 RegexBuilder学习指南
  • 248
分享到

Swift 中的 RegexBuilder学习指南

Swift RegexBuilderSwift 学习 2023-05-14 20:05:21 248人浏览 泡泡鱼
摘要

目录前言Regex 字面量RegexBuilder - 像写代码一样写正则RegexRepetitionBehaviorFoundation 的支持总结前言 在我们日常的项目开发中

前言

在我们日常的项目开发中,经常会碰到和正则表达式打交道的时候。比如用户密码,通常会要求同时包含小写字母、大写字母、数字,并且长度不少于 8 位,以此来提高密码的安全性。

在 Swift 中,我们可以用正则表达式的字面量方式来进行实现。

Regex 字面量

Regex 字面量实现代码:

let regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/
let text = "Aa11111111"
print(text.matches(of: regex).first?.output) // Optional("Aa11111111")

通过上述代码可以看到,//通过两个斜线就可以来生成正则的字面量。用字面量的方式确实可以使代码很简洁,但简洁的代价就是很难看懂,对后面的代码维护也造成了很大的困难。

就像网上盛传的一句梗一样:“我有一个问题,所以我写了一个正则表达式。现在,我有了两个问题。”😂

对于 Regex 难懂且难维护的问题,Swift 的开发团队给出的方案就是:RegexBuilder。

RegexBuilder - 像写代码一样写正则

假设我们有一个字符串"name: John Appleseed, user_id: 100",想要提取其中user_id的值。 首先第一步,先导入 RegexBuilder:

import RegexBuilder

接着,通过结构体 Regex 来构建正则语句:

let regex = Regex {
    "user_id:" // 1
    OneORMore(.whitespace) // 2
    Capture(.localizedInteger(locale: Locale(identifier: "zh-CN"))) // 3
}

第一行代码匹配的是固定字符串:"user_id",第二行代码匹配的是一个或者多个空格,第三行代码则是匹配的整型数字。

localizedInteger 会将匹配到的数字自动转为整型,比如下面的例子:

let input = "user_id:  100.11"
let regex = Regex {
    Capture(.localizedInteger(locale: Locale(identifier: "zh-CN")))
}
if let match = input.firstMatch(of: regex) {
    print("Matched: \(match.0)") // Matched:  100.11
    print("User ID: \(match.1)") // User ID: 100
}

虽然匹配的是 100.11,但输出的仍然是 100。

最后,就可以通过 Macth 的相关函数来进行数据提取了:

if let match = input.firstMatch(of: regex) {
    print("Matched: \(match.0)")
    print("User ID: \(match.1)")
}

RegexRepetitionBehavior

该结构体是用来定义匹配的重复行为的,它有三个值:

  • edger:会尽可能多的去匹配输入的字符,必要的时候会回溯。默认为edger
  • reluctant:会尽可能少的去匹配输入的字符,它会根据你的需求来一点点增大匹配区域,以完成匹配。
  • possessive:会尽可能多的去匹配输入的字符,不会回溯。

比如下面这个例子:

let testSuiteTestInputs = [    "2022-06-06 09:41:00.001",    "2022-06-06 09:41:00.001.",    "2022-06-06 09:41:00.001."]
let regex = Regex {
    Capture(OneOrMore(.any))
    Optionally(".")
}
for line in testSuiteTestInputs {
    if let (dateTime) = line.wholeMatch(of: regex)?.output {
        print("Matched: \(dateTime)\"")
    }
}

因为这三条数据最后的.是不一定有的,所以我们的正则有一个 Optionally(".")。但匹配出来的 dateTime 还是会带 .。因为 edger 会匹配所有的字符包含最后的点在内,这样 Optionally(".") 根本不会起作用。

改成 Capture(OneOrMore(.any, .reluctant))则会修复这个问题。因为 reluctant 它是匹配尽可能少的输入,所以最后的Optionally(".")会执行。

在 Swift 5.7 中,Foundation 框架也对 RegexBuilder 进行适配。所以对于 Date、URL等类型,我们可以借助 Foundation 的强大功能来进行解析。

Foundation 的支持

假如,我们在做一个金融相关的 APP,为了兼容一些老数据,需要将一些字符串类型的数据转为结构体。

这是我们的字符串数据:

let statement = """
CREDIT    2022/03/03    张三     ¥2,000,000.00
DEBIT     03/03/2022    Tom      $2,000,000.00
DEBIT

这是我们需要转的结构体:

struct Trade {
    let type: String
    let date: Date
    let name: String
    let count: Decimal
}

下面这个就是我们需要编写的 Regex:

let regex = Regex {
    Capture {
        /CREDIT|DEBIT/
    }
    OneOrMore(.whitespace)
    Capture {
        One(.date(.numeric, locale: Locale(identifier: "zh_CN"), timeZone: .gmt))
    }
    OneOrMore(.whitespace)
    Capture {
        OneOrMore(.Word)
    }
    OneOrMore(.whitespace)
    Capture {
        One(.localizedCurrency(code: "CNY", locale: Locale(identifier: "zh_CN")))
    }
}

首先,我们需要匹配固定的字符串:CREDIT/DEBIT,接着是匹配一个或者多个空格。

接下来就是 Foundation 的重头戏了,对于日期类型的字符串,我们并不需要写一些匹配年月日规则的正则,只需要借助 Foundation 内嵌的功能即可。这样做不仅省去了我们自己编写的时间,更重要的是:官方写的要比我们自己写的更能保证代码的正确性。

需要注意的是,Apple 推荐我们显式的写出 locale 属性,而不是下面这种跟随系统写法 :

One(.date(.numeric, locale: Locale.current, timeZone: TimeZone.current))

因为这种写法会带来多种预期,并不能保证数据的确定性。

匹配完日期,接着就是对空格和用户名的匹配。最后,是对交易金额的匹配,金额也是 Foundation 提供的函数来进行的匹配。

测试代码:

let result = statement.matches(of: regex)
var trades = [Trade]()
result.forEach { match in
    let (_, type, date, name, count) = match.output
    trades.append(Trade(type: String(type), date: date, name: String(name), count: count))
}
print(trades) 
// [SwiftDemo.Trade(type: "CREDIT", date: 2022-03-03 00:00:00 +0000, name: "张三", count: 2000000), SwiftDemo.Trade(type: "DEBIT", date: 2022-03-05 00:00:00 +0000, name: "李三", count: 33.27)]

通过打印可以得知,输出的结果并不符合预期,漏掉了 Tom 那条数据。漏掉的原因可以通过代码一眼得知:因为对日期和金额我们显式的指定了是中国的格式,显然03/03/2022 这种格式是不符合年月日的格式的。这也体现了显式指定格式的好处:方便排查问题。

我们只要将日期格式转为年月日格式,再将 $ 转为 ¥ 即可让正则正确匹配。

首先,我们需要根据 currency 来来返回正确的 Date 类型:

func pickStrategy(_ currency: Substring) -> Date.ParseStrategy {
  switch currency {
  case "$": return .date(.numeric, locale: Locale(identifier: "en_US"), timeZone: .gmt)
  case "¥": return .date(.numeric, locale: Locale(identifier: "zh_CN"), timeZone: .gmt)
  default: fatalError("We found another one!")
  }
}

接着,编写正则表达式来获取相应的字符串字段:

let regex1 = #/
  (?<date>     \d{2} / \d{2} / \d{4})
  (?<name>   \P{currencySymbol}+)
  (?<currency> \p{currencySymbol})
/#

注:#//#格式为 Swift 中运行时正则表达式的格式。

最后,再调用 replace 函数来进行符合正则的字符替换:

statement.replace(regex1) { match -> String in
    print(match.currency)
    let date = try! Date(String(match.date), strategy: pickStrategy(match.currency))
    // ISO 8601, it's the only way to be sure
    let newDate = date.formatted(.iso8601.year().month().day())
    return newDate + match.name + "¥"
  }
statement = statement.replacinGoccurrences(of: "-", with: "/")

这样,我们就能解析出符合我们需求的 Trade 类型的数据了。

总结

  • RegexBuilder 会使代码更加易读易维护
  • RegexRepetitionBehavior 的三个值的区别
  • 尽可能多的使用 Foundation 提供的函数来解析数据
  • 使用 Foundation 时要指定格式解析数据,这样可以保证数据的唯一性

参考链接

  • 用户密码正则表达式来源
  • RegexBuilder

以上就是Swift 中的 RegexBuilder学习指南的详细内容,更多关于Swift RegexBuilder的资料请关注编程网其它相关文章!

--结束END--

本文标题: Swift 中的 RegexBuilder学习指南

本文链接: https://www.lsjlt.com/news/204516.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Swift 中的 RegexBuilder学习指南
    目录前言Regex 字面量RegexBuilder - 像写代码一样写正则RegexRepetitionBehaviorFoundation 的支持总结前言 在我们日常的项目开发中...
    99+
    2023-05-14
    Swift RegexBuilder Swift 学习
  • Swift 中 Opaque Types学习指南
    目录什么是Opaque Types如何使用为什么要使用可读性更强性能更好使用的限制总结什么是Opaque Types Opaque Types 是在 Swift5.7 新添加的一个...
    99+
    2023-05-14
    Swift Opaque Types Swift 学习指南
  • Swift中的RegexBuilder怎么正确使用
    本篇内容主要讲解“Swift中的RegexBuilder怎么正确使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Swift中的RegexBuilder怎么正确使用”吧!前言在我们日常的项目开发...
    99+
    2023-07-05
  • MySQL5认证学习指南
    MySQL5认证学习指南: Detail:MySQL5认证学习指南[@more@] ...
    99+
    2024-04-02
  • JavaScript的学习指南是怎样的
    本篇文章为大家展示了JavaScript的学习指南是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。JavaScript是一种属于网络的脚本语言,已经被广泛用于...
    99+
    2024-04-02
  • 4.《python自省指南》学习
    前言   前面几篇博客我都是通过python自省来分析代码并试图得出结论。当然,仅仅通过自省能解决的问题有限,但遇到问题还是不自主的去用这个功能,觉得对于认识代码的含义还是有一定帮助的。而这些自省的知识我都是从python自省指南中学习的...
    99+
    2023-01-30
    指南 python
  • linux shell脚本学习指南
    从头一来二去阅读语法和命令说明,对于脚本小白来说比较枯燥,难以坚持,所以这里选择对一份完整的shell脚本代码来逐行逐段解读,希望可以渡一渡小白,帮助我们快速进入脚本的大门。 老司机...
    99+
    2024-04-02
  • CSS中的position定位及用法学习指南
    了解什么是CSS中的position定位及其用法,需要具体代码示例CSS(层叠样式表)是一种用于描述网页样式和布局的标记语言。在网页开发中,经常会使用CSS来控制元素的位置和布局。其中,position属性是CSS中常用的定位属性之一。本文...
    99+
    2023-12-27
    position定位 CSS中的position position用法
  • 学习Golang:简明入门指南
    Golang(也称为Go)是一种由Google开发的开源编程语言,它具有高效的并发性能和简洁的语法特性,在近年来逐渐成为程序员们瞩目的热门选择。本文将介绍Golang的基本概念和语法特...
    99+
    2024-02-23
    指南 golang 快速入门
  • GO语言学习指南:有效提升学习效率
    1. 入门准备 确保您拥有稳定的网络连接和一台能够运行 Go 语言编译器的计算机。 安装 Go 语言编译器和开发环境。 熟悉基本编程概念,如变量、数据类型、控制流和函数。 2. 选择学习资源 官方文档:...
    99+
    2024-01-31
    go语言 学习指南 提升效率 在线课程
  • Python PyTorch:深度学习入门指南
    ## PyTorch深度学习入门指南 PyTorch是一个流行的开源机器学习框架,基于Python开发,因其灵活性和易用性而受到广泛欢迎。本指南将带领您从零开始,快速入门PyTorch,并为您提供必要的知识和资源,帮助您使用PyTorch...
    99+
    2024-02-02
    深度学习,PyTorch,TensorFlow,神经网络,机器学习
  • PHP中的教育学习管理系统开发指南
    PHP是一种广泛使用的服务器端脚本语言,它可以用于Web开发,特别是适用于动态网页开发。在教育领域,PHP也被广泛应用于教育学习管理系统的开发。学习管理系统是一种基于Web的软件应用程序,用于协助教师或管理员管理学生的学习过程。本文将分享一...
    99+
    2023-05-20
    PHP 教育学习 管理系统
  • 学习PyCharm:调整字体大小的指南
    PyCharm是一款功能强大的Python集成开发环境(IDE),很多Python开发者喜欢使用PyCharm来编写和调试他们的代码。然而,有时候PyCharm的默认字体大小可能不适合每个人的阅读习惯。幸运的是,PyCharm提...
    99+
    2024-02-02
    pycharm 调整 字体
  • C++技术中的机器学习:使用C++部署机器学习模型的指南
    在 c++++ 中部署机器学习模型的步骤包括:准备模型、加载模型、预处理数据、执行预测和评估结果。使用 c++ 部署模型的示例代码包括加载模型、预处理数据和执行预测。实战案例展示了如何使...
    99+
    2024-05-12
    机器学习 c++
  • 如何入门Python——学习Python的指南针
    ✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识...
    99+
    2023-09-02
    python 学习 爬虫
  • php学习,从初学者到专家的完整指南
    P跳转到PHP:从初学者到专家的完整指南在现代的Web开发中,熟练掌握PHP已经成为一个必备的技能。PHP是一种流行的服务器端编程语言,由于其易学易用和良好的扩展性而备受欢迎。PHP向开发者提供了许多有用的工具和内容,可以用于创建各种类型的...
    99+
    2023-05-14
  • 实战应用Android进阶学习指南
    作者:禅与计算机程序设计艺术 1.简介 1.1 前言 在软件开发的历史上,从最初的手工编码到后来的脚本编程、GUI编程、打包工具、编译器等各种工具的出现,使得程序员可以将复杂的代码转换成可执行的程序...
    99+
    2023-10-23
    大数据 人工智能 语言模型 Java Python 架构设计
  • Spring Boot DevTools 全局配置学习指南
    目录 一、直接重启项目与devtools重启的区别 二、DevTools配置 三、DevTools全局配置 四、trigger-file控制重启行为 4.1、配置 4.2、新建文件....
    99+
    2024-04-02
  • Django学习笔记之View操作指南
    Django的View 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。响应可以是一张网页的HTML内容,一个重定向,一个4...
    99+
    2024-04-02
  • Vue Jest实战指南:step-by-step学习
    单元测试 单元测试是测试软件中最小的独立模块,通常是一个函数或方法。在Vue.js中,我们可以使用Jest的describe()和it()函数来编写单元测试。 describe("MyComponent", () => { it...
    99+
    2024-02-04
    Vue.js Jest 单元测试 集成测试 端到端测试 测试实用工具
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作