2015-06-27 61 views
0

我試圖使NSRegularExpression捕獲組模式。我有串abc{=2}和正則表達式模式{(.+)}獲得=2字符串,但每次嘗試創建NSRegularExpression實例與捕獲組不能與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

+0

你的答案應該工作。但它不是標準。許多語言等甚至不讓你看看,但大多數允許捕獲組。 –

回答

2

這是一個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相同的結果)。

+0

謝謝,花了一段時間與貧民窟範圍抵消戰鬥。 –

0

我使用不同的模式解決了這個問題。我現在不知道regex101.com是否與它匹配錯誤,並且我的模式的正確匹配是{=2}而不是'= 2'。

我用積極lookbehead和積極的前瞻來配合這一點。這是一種模式:

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