swift 5.7 开始让正则变得如此简单
# Regex
Regex 类型是 iOS 16 新出的一个类型,利用这个类型可以很容易地生成正则表达式:
```
let pat = #"(\d+)"#
let reg = try Regex(pat)
```
这种创建方式和 NSRegularExpression 差不多,你需要将特殊符号用反斜杠标记,使用 try 来捕获异常情况。
为了不出现上面的创建步骤,swift 出了一种使用两个斜杠"/.../"来直接生成 Regex 的方法,以上代码等同于:
```
let reg = /(\d+)/
```
通过正则语法糖的方式生成正则表达式时,可以在编译器检查是否有语法错误,同时还有 Xcode 语法突出显示。
例如使用这个表达式可以检测字符串中的名称和数字
```
let reg = /(\w+)\s+(\d+)/
let ipt = "ABC 123 abc"
if let rst = ipt.firstMatch(of: reg) {
print(rst.0) // ABC 123
print(rst.1) // ABC
print(rst.2) // 123
}
```
输出的结果是一个元组,第一个值正则表达式匹配的所有内容,第二个值是捕获的第一个子字符串,第三个值是捕获的第二个子字符串,以此类推。
当然页可以用元组命名每个属性的名字
```
let reg = /(\w+)\s+(\d+)/
let ipt = "ABC 123 abc"
if let (matched, name, count) = ipt.firstMatch(of: reg)?.output {
print(matched) // ABC 123
print(name) // ABC
print(count) // 123
}
```
还可以在正则表达式里直接命名捕获的变量
```
let ipt = "ABC 123 abc"
let reg = /(?<name>\w+)\s+(?<count>\d+)/
if let match = ipt.firstMatch(of: reg) {
print(match.name) // ABC
print(match.count) // 123
}
```
# 匹配方式
swift 提供了几种不同的方法,可以用来匹配正则表达式
```
//首个匹配
ipt.firstMatch(of: regex)
//前缀匹配
ipt.prefixMatch(of: regex)
//完整匹配
ipt.wholeMatch(of: regex)
let l1 = "ABC 123"
// 将空格替换成逗号
let l2 = l1.replacing(/\s+/,with:",") // ABC,123
// 去除字母和空格
let l3 = l1.trimmingPrefix(/\w+\s+/) // 123
// 使用空格拆分
let fs = l1.split(separator: /\s+/) // ["ABC","123"]
```
# 正则表达式生成器
swift 还提供了正则表达式构建器 DSL,以更结构化和更高可读性的方法来构建你想要的正则表达式。
首先导入 RegexBuilder 模块
```
import RegexBuilder
```
然后构建正则表达式
```
let reg = Regex {
Capture {
OneOrMore(.word) // 一个或多个单词
}
OneOrMore(.whitespace) // 一个或多个空格
Capture {
OneOrMore(.digit) // 一个或多个数字
}
}
let input = "ABC 123 abc"
if let match = input.firstMatch(of: reg) {
let s1 = match.1 // ABC
let n1 = match.2 // 123
}
```
有了这套 DSL 构建器之后,正则将会简单很多(当然还是要记住这些规则才行),除了上边用到的 OneOrMore 之外,还有很多可用的语法表达式,以下是一些常用的:
+ One 精确匹配出现一次
+ OneOrMore 匹配出现一次或多次
+ ZeroOrMore 匹配出现零次或一次
+ Lookahead 仅当其内容在给定位置匹配时才允许匹配继续
+ NegativeLookahead 仅当其内容在给定位置不匹配时才允许继续匹配
+ Repeat 指定次数的匹配
其中可输入的常用参数有:
+ .any 与任何元素匹配的字符类
+ .anyNonNewline 与任何非换行符元素匹配的字符类
+ .digit 任意数字
+ .hexDigit 任何十六进制数字
+ .word 任何单词字符
+ .whitespace 任何空格字符
我的笔记