Michael Kunzmann Michael Kunzmann - 6 months ago 98
iOS Question

Swift extract regex matches

I want to extract substrings from a string that match a regex pattern.

So I'm looking for something like this:

func matchesForRegexInText(regex: String!, text: String!) -> [String] {
???
}


So this is what I have:

func matchesForRegexInText(regex: String!, text: String!) -> [String] {

var regex = NSRegularExpression(pattern: regex,
options: nil, error: nil)

var results = regex.matchesInString(text,
options: nil, range: NSMakeRange(0, countElements(text)))
as Array<NSTextCheckingResult>

/// ???

return ...
}


The problem is, that
matchesInString
delivers me an array of
NSTextCheckingResult
, where
NSTextCheckingResult.range
is of type
NSRange
.

NSRange
is incompatible with
Range<String.Index>
, so it prevents me of using
text.substringWithRange(...)


Any idea how to achieve this simple thing in swift without too many lines of code?

Answer

Even if the matchesInString() method takes a String as the first argument, it works internally with NSString, and the range parameter must be given using the NSString length and not as the Swift string length. Otherwise it will fail for "extended grapheme clusters" such as "flags".

So you should convert the given Swift string to an NSString and then extract the ranges. The result will be converted to a Swift string array automatically:

func matchesForRegexInText(regex: String!, text: String!) -> [String] {

    let regex = NSRegularExpression(pattern: regex,
        options: nil, error: nil)!
    let nsString = text as NSString
    let results = regex.matchesInString(text,
        options: nil, range: NSMakeRange(0, nsString.length))
        as! [NSTextCheckingResult]
    return map(results) { nsString.substringWithRange($0.range)}
}

Example:

let string = "
Comments