Swift中如何获取正则表达式匹配结果的范围?
在Swift中获取正则表达式匹配结果的范围
嘿,我来帮你搞定这个问题!你已经有了正确的正则表达式,现在只需要用NSRegularExpression来获取所有匹配项的范围就好——毕竟range(of:options:.regularExpression)只能返回第一个匹配的范围,没法处理多个匹配的场景,而NSRegularExpression能完美解决这个问题。
下面是具体的实现步骤和代码示例:
1. 核心思路
我们需要:
- 用
NSRegularExpression编译你的正则表达式 - 获取所有匹配结果,每个结果包含了整个匹配项的范围,以及每个分组的范围
- 将
NSRange(Objective-C风格的范围)转换为Swift原生的Range<String.Index>,确保和Swift字符串的索引兼容
2. 完整代码示例
import Foundation // 你的输入字符串 let inputString = "我有一个包含@{1 | Tom Lofe}和@{2 | Cristal Dawn}的字符串" // 你的正则表达式(注意转义反斜杠) let regexPattern = "@\\{(\\d+) ?\\| ?(\\w+ *?\\w*?)\\}" do { // 编译正则表达式,处理可能的错误(比如正则格式无效) let regex = try NSRegularExpression(pattern: regexPattern) // 指定要搜索的整个字符串范围 let fullStringRange = NSRange(inputString.startIndex..., in: inputString) // 获取所有匹配结果 let matches = regex.matches(in: inputString, range: fullStringRange) // 遍历每个匹配项 for (index, match) in matches.enumerated() { print("=== 第\(index+1)个匹配项 ===") // 获取整个匹配项的范围和内容 guard let fullMatchRange = Range(match.range, in: inputString) else { continue } let fullMatchContent = inputString[fullMatchRange] print("完整匹配内容:\(fullMatchContent)") print("完整匹配范围:\(fullMatchRange)") // 获取第一个分组(数字部分)的范围和内容 guard let numberRange = Range(match.range(at: 1), in: inputString) else { continue } let numberContent = inputString[numberRange] print("数字分组内容:\(numberContent)") print("数字分组范围:\(numberRange)") // 获取第二个分组(名字部分)的范围和内容 guard let nameRange = Range(match.range(at: 2), in: inputString) else { continue } let nameContent = inputString[nameRange] print("名字分组内容:\(nameContent)") print("名字分组范围:\(nameRange)\n") } } catch { print("正则表达式编译失败:\(error.localizedDescription)") }
3. 关键细节说明
- NSRange转Swift Range:因为Swift字符串是基于Unicode标量的,而
NSRange是基于UTF-16编码的,所以必须用Range(_:in:)方法转换,避免索引越界或错误。 - 处理多个匹配:
matches(in:range:)会返回所有符合条件的匹配结果,每个NSTextCheckingResult对象都包含了整个匹配和每个分组的NSRange。 - 错误处理:创建
NSRegularExpression时可能抛出错误(比如正则格式错误),所以必须用do-catch包裹。
如果你只需要第一个匹配的范围,也可以用range(of:)的简化写法,但局限性很大:
if let range = inputString.range(of: regexPattern, options: .regularExpression) { print("第一个匹配的范围:\(range)") }
但显然你的场景需要处理多个匹配,所以NSRegularExpression是最佳选择。
内容的提问来源于stack exchange,提问作者Riyan Fransen




