捕获组不适用于NSRegularExpression

时间:2015-06-27 16:44:58

标签: regex swift nsregularexpression

我正在尝试让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

2 个答案:

答案 0 :(得分:2)

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

一个例子:

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处)。通过使用前瞻/后瞻,您已经完全从模式中有效地排除了{}大括号。如果检查结果,您应该看到捕获组结果实际存在于索引1处(但与索引0的结果相同)。

答案 1 :(得分:0)

我用不同的模式修复了这个问题。我现在不知道如果regex101.com错误地匹配它并且我的模式的正确匹配是{=2}而不是&#39; = 2&#39;。

我使用积极的lookbehind和积极的前瞻来匹配这个。这是模式:

(?<=\\{)(.+)(?=\\})