【问题标题】:Capturing group does not work with NSRegularExpression捕获组不适用于 NSRegularExpression
【发布时间】:2015-07-07 02:35:48
【问题描述】:

我正在尝试使 NSRegularExpression 使用捕获组模式。我有字符串abc{=2} 和正则表达式模式{(.+)} 来获取=2 字符串,但是每次创建NSRegularExpression 实例的尝试都以

结尾
Optional(Error Domain=NSCocoaErrorDomain Code=2048 "The operation couldn’t be completed. (Cocoa error 2048.)" UserInfo=0x7fad7253cb40 {NSInvalidValue={(.+)}})

代码:

var error: NSError?
let regexp = NSRegularExpression(pattern: "{(.+)}", options: .CaseInsensitive, error: &error)
println("error = \(error)")

我找不到这种模式有什么问题。我正在使用 regex101.com 页面,它在那里工作。

提前谢谢你!

编辑

我看到转义大括号 (\\{(.+)\\}) 解决了错误问题,但后来我得到了 {=2} 而不是 =2。

【问题讨论】:

  • 您的答案应该有效。但这不是标准的。许多语言等甚至不允许您进行环视,但大多数允许捕获组。

标签: regex swift nsregularexpression


【解决方案1】:

这是NSRegularExpression 的一个特点,也许NSTextCheckingResult 更是如此。您捕获的范围实际上是您的NSTextCheckingResult 结果实例的索引1 处的范围。

一个例子:

let rx = NSRegularExpression(pattern: "\\{(.+?)\\}", options: .CaseInsensitive, error: nil)!
let str = "abc{=2}"
let strRange = NSMakeRange(0, count(str))

rx.enumerateMatchesInString(str, options: nil, range: strRange, usingBlock: { result, flags, stop in
    if let range0 = result?.range {
        println( (str as NSString).substringWithRange(range0) ) // "{=2}"
    }
    if let range1 = result?.rangeAtIndex(1) {
        println( (str as NSString).substringWithRange(range1) ) // "=2" <-- this is what you want!
    }
})

对于每个NSTextCheckingResult 实例,索引0 处的范围是表示捕获整个模式的范围(range 属性是索引0 的快捷方式)。您的捕获组的范围保存在索引1 及以上。 From the NSTextCheckingResult docs rangeAtIndex: method:

一个结果必须至少有一个范围,但可以选择有更多(例如,表示正则表达式捕获组)。

理解这一点的最简单方法是假设您提供了一个没有捕获组的正则表达式模式。 NSTextCheckingResult 实例将匹配和表示什么?整个匹配的模式!

在尝试访问捕获组的范围之前,最好使用NSTextCheckingResult's numberOfRanges property 确保捕获的范围超过 1 个。如果您正在使用一个捕获组,则当您的捕获组找到匹配项时,您应该期望 numberOfRanges 为 2。

最后,虽然这不是必需的,但我将? 修饰符添加到您的捕获组(.+) 以生成(.+?)。您的模式最初在捕获组内是贪婪的,? 使模式非贪婪。我发现在使用正则表达式时,非贪婪通常更容易预测。


我还应该提到您的解决方案有效的原因(结果在索引 0 处)。通过使用lookahead/lookbehind,您有效地从您的模式中完全排除了{} 大括号。如果您检查结果,您应该会看到您的捕获组结果实际上存在于索引 1 处(但给出的结果与索引 0 相同)。

【讨论】:

  • 谢谢,花了一些时间用 ghetto range offsets 来解决这个问题。
【解决方案2】:

我使用不同的模式解决了这个问题。我现在不知道 regex101.com 是否匹配错误,我的模式的正确匹配是 {=2} 而不是 '=2'。

我使用了积极的后视和积极的前瞻来匹配这一点。这是模式:

(?&lt;=\\{)(.+)(?=\\})

【讨论】:

    猜你喜欢
    • 2011-10-12
    • 2015-10-08
    • 2014-09-08
    • 2011-06-12
    • 2015-10-03
    • 2016-06-20
    • 1970-01-01
    • 2018-08-30
    • 2019-02-26
    相关资源
    最近更新 更多