Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to group search regular expressions using swift

Tags:

regex

swift

In regular expressions you can group different matches to easily "pattern match" a given match.

while match != nil {
  match = source.rangeOfString(regex, options: .RegularExpressionSearch)
  if let m = match {
    result.append(source.substringWithRange(m)
      source.replaceRange(m, with: "") 
  }
}

The above works find to find a range of the match, but it cannot tell me the group. For instance if I search for words encapsulated in "" I would like to match a "word" but quickly fetch only word

Is it possible to do so in swift?

like image 671
chrs Avatar asked Nov 21 '14 18:11

chrs


2 Answers

Swift is pretty ugly right now with regular expressions -- let's hope for more-native support soon! The method on NSRegularExpression you want is matchesInString. Here's how to use it:

let string = "This is my \"string\" of \"words\"."
let re = NSRegularExpression(pattern: "\"(.+?)\"", options: nil, error: nil)!
let matches = re.matchesInString(string, options: nil, range: NSRange(location: 0, length: string.utf16Count))

println("number of matches: \(matches.count)")

for match in matches as [NSTextCheckingResult] {
    // range at index 0: full match
    // range at index 1: first capture group
    let substring = (string as NSString).substringWithRange(match.rangeAtIndex(1))
    println(substring)
}

Output:

number of matches: 2
string
words
like image 75
Nate Cook Avatar answered Oct 03 '22 19:10

Nate Cook


You can use this if you want to collect the matched strings. (My answer is derived from Nate Cooks very helpful answer.)

Updated for Swift 2.1

extension String {
    func regexMatches(pattern: String) -> Array<String> {
        let re: NSRegularExpression
        do {
            re = try NSRegularExpression(pattern: pattern, options: [])
        } catch {
            return []
        }

        let matches = re.matchesInString(self, options: [], range: NSRange(location: 0, length: self.utf16.count))
        var collectMatches: Array<String> = []
        for match in matches {
            // range at index 0: full match
            // range at index 1: first capture group
            let substring = (self as NSString).substringWithRange(match.rangeAtIndex(1))
            collectMatches.append(substring)
        }
        return collectMatches
    }
}

Updated for Swift 3.0

extension String {
func regexMatches(pattern: String) -> Array<String> {
    let re: NSRegularExpression
    do {
        re = try NSRegularExpression(pattern: pattern, options: [])
    } catch {
        return []
    }

    let matches = re.matches(in: self, options: [], range: NSRange(location: 0, length: self.utf16.count))
    var collectMatches: Array<String> = []
    for match in matches {
        // range at index 0: full match
        // range at index 1: first capture group
        let substring = (self as NSString).substring(with: match.rangeAt(1))
        collectMatches.append(substring)
    }
    return collectMatches
}}
like image 37
zekel Avatar answered Oct 03 '22 19:10

zekel