You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动