通过在Swift中使用正则表达式进行匹配来获取所有可能的范

时间:2017-04-12 04:24:50

标签: regex swift

我在Swift中使用以下代码为应用程序构建适当的正则表达式:

let regExp = "-(\\([0-9.a-z()+-×÷√^₁₀²³/]+\\)|[0-9.a-z()+-×÷√^₁₀²³/]+)"

let testString = "-(hsjshdf)   -hsghsgsgs -(k) -(1/64) -dhsg62 -(p)"

let regularExpression = try! NSRegularExpression(pattern: regExp, options: [])

let matchesArray = regularExpression.matches(in: testString, options: [], range: NSRange(location: 0, length: testString.characters.count))

for match in matchesArray {
    for i in 0..<match.numberOfRanges {
        let range = match.rangeAt(i)
        let r = testString.index(testString.startIndex, offsetBy: range.location) ..< testString.index(testString.startIndex, offsetBy: range.location + range.length)
        print(testString.substring(with: r))
    }
}

我得到的结果如下:

-(hsjshdf)
(hsjshdf)
-hsghsgsgs
hsghsgsgs
-(k)
(k)
-(1/64)
(1/64)
-dhsg62
dhsg62
-(p)
(p)

但是,我想要正则表达式匹配并将子字符串分组在&#34;()&#34;中,这样我就可以获得以下输出:

-(hsjshdf)
(hsjshdf)
hsjshdf
-hsghsgsgs
hsghsgsgs
-(k)
(k)
k
-(1/64)
(1/64)
1/64
-dhsg62
dhsg62
-(p)
(p)
p

我尝试了对原始正则表达式的以下修改,它适用于子串&#34 ;-(hsjshdf)&#34;但在打印子串的匹配时崩溃了#34; -hsghsgsgs&#34;执行时错误(致命错误:无法超出endIndex):

let regExp = "-(\\(([0-9.a-z()+-×÷√^₁₀²³/]+)\\)|[0-9.a-z()+-×÷√^₁₀²³/]+)"

我不熟悉NSRegularExpression。我使用错误的正则表达式吗?我需要设置一个特殊选项吗?

感谢您的帮助。最诚挚的问候。

/ TB

1 个答案:

答案 0 :(得分:1)

事实上,问题在于循环。

你知道你的正则表达式let regExp = "-(\\(([0-9.a-z()+-×÷√^₁₀²³/]+)\\)|[0-9.a-z()+-×÷√^₁₀²³/]+)"中有两对捕获括号,而后者(内部)可能无法捕获字符串的任何部分。

您应该知道的一件事是NSRegularExpression返回NSRange(location: NSNotFound, length: 0)以查找遗失的捕获内容。在当前的实现中,NSNotFoundInt.max具有相同的值,可能远远大于任何实际的字符串。

在使用之前,您只需要检查范围的location是否为NSNotFound

let regExp = "-(\\(([0-9.a-z()+-×÷√^₁₀²³/]+)\\)|[0-9.a-z()+-×÷√^₁₀²³/]+)"

let testString = "-(hsjshdf)   -hsghsgsgs -(k) -(1/64) -dhsg62 -(p)"

let regularExpression = try! NSRegularExpression(pattern: regExp, options: [])

//###(1) Use `.utf16.count`, not `.characters.count`.
let matchesArray = regularExpression.matches(in: testString, options: [], range: NSRange(location: 0, length: testString.utf16.count))

for match in matchesArray {
    for i in 0..<match.numberOfRanges {
        let range = match.rangeAt(i)
        if range.location == NSNotFound {continue} //###(2) Skip missing captures.
        //###(3) Your way of creating `r` does not work for non-BMP characters.
        print((testString as NSString).substring(with: range))
    }
}

(我的评论(1)和(3)对您的输入testString并不重要,但您也应该知道NSRegularExpressionNSString一起使用,以UTF表示内部基于16格式。locationlength表示基于UTF-16的偏移和计数,而不是基于Characters。)