RegEx
是 NSRegularExpression
的一个轻量级封装,用于在 Swift 中更轻松地进行正则表达式测试、数据提取和替换。
test()
测试字符串是否匹配表达式numberOfMatches(in:)
确定字符串中匹配的数量matches(in:)
检索字符串中的所有匹配项firstMatch(in:)
检索第一个匹配项,无需处理所有匹配项iterator()
和 next()
高效地迭代匹配项生成的 Match
结构包含 完整匹配、任何 捕获组 以及相应的 Swift 字符串范围。
通过使用 Range<String.Index>
和 Substring
,RegEx.Match
能够返回所有这些信息,而无需复制输入字符串中的数据 👏
给定一个字符串
let str = "16^32=2^128"
定义一个表达式,例如识别指数表示法 (^
),同时捕获指数值
let expression = "\\d+\\^(\\d+)"
使用正则表达式
let regex = try RegEx(pattern: expression)
regex.test(str) // true
regex.numberOfMatches(in: str) // 2
let first = regex.firstMatch(in: str) // 1 match with 1 captured group
first?.values // ["16^32", "32"]
let matches = regex.matches(in: str) // 2 matches with 1 captured group each
matches[0].values // ["16^32", "32"]
matches[1].values // ["2^128", "128"]
let iterator = regex.iterator(for: str) // Iterate over matches one by one
iterator.next()?.values // ["16^32", "32"]
iterator.next()?.values // ["2^128", "128"]
iterator.next() // nil
let regex = try RegEx(pattern: #"(\d)(\d)"#)
let result = regex.replaceMatches(in: "1234", withTemplate: "$2$1")
// result: 2143
let regex = try RegEx(pattern: #"(\w+)\b"#)
let result = regex.replaceMatches(in: "Hello world!") { match in
let value = String(match.values[0] ?? "")
return String(value.reversed())
}
// result: olleH dlrow!
没有框架,只需复制粘贴!
public class RegEx {
private let regex: NSRegularExpression
public init(pattern: String, options: NSRegularExpression.Options = []) throws {
regex = try NSRegularExpression(pattern: pattern, options: options)
}
public struct Match {
public let values: [Substring?]
public let ranges: [Range<String.Index>?]
}
public func numberOfMatches(in string: String, from index: String.Index? = nil) -> Int {
let startIndex = index ?? string.startIndex
let range = NSRange(startIndex..., in: string)
return regex.numberOfMatches(in: string, range: range)
}
public func firstMatch(in string: String, from index: String.Index? = nil) -> Match? {
let startIndex = index ?? string.startIndex
let range = NSRange(startIndex..., in: string)
let result = regex.firstMatch(in: string, range: range)
return result.flatMap { map(result: $0, in: string) }
}
public func matches(in string: String, from index: String.Index? = nil) -> [Match] {
let startIndex = index ?? string.startIndex
let range = NSRange(startIndex..., in: string)
let results = regex.matches(in: string, range: range)
return results.map { map(result: $0, in: string) }
}
public func test(_ string: String) -> Bool {
return firstMatch(in: string) != nil
}
func map(result: NSTextCheckingResult, in string: String) -> Match {
let ranges = (0..<result.numberOfRanges).map { index in
Range(result.range(at: index), in: string)
}
let substrings = ranges.map { $0.flatMap { string[$0] }}
return Match(values: substrings, ranges: ranges)
}
}
extension RegEx {
public class Iterator: IteratorProtocol {
let regex: RegEx
let string: String
var current: RegEx.Match?
init(regex: RegEx, string: String) {
self.regex = regex
self.string = string
current = regex.firstMatch(in: string)
}
public func next() -> RegEx.Match? {
defer {
current = current.flatMap {
let index = $0.ranges[0]?.upperBound
return self.regex.firstMatch(in: self.string, from: index)
}
}
return current
}
}
public func iterator(for string: String) -> Iterator {
return Iterator(regex: self, string: string)
}
}
实际上,我喜欢单元测试,所以我把这个仓库做成了一个 Swift 包,可以使用 Swift 包管理器导入和使用。
将以下代码添加到您的 Package.swift
dependencies: [
.package(url: "https://github.com/eneko/RegEx.git", from: "0.1.0")
],
targets: {
.target(name: "YourTarget", dependencies: ["RegEx"])
}
如果您好奇,可以使用 $ swift test
或 $ swift test --parallel
运行测试。