如何使用swift对正则表达式进行分组

时间:2014-11-21 18:00:28

标签: regex swift

在正则表达式中,您可以轻松地对不同的匹配进行分组"模式匹配"给定的比赛。

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

上述作品找到了一系列的匹配,但它不能告诉我这个组。例如,如果我搜索封装在""我想要匹配一个"字"但很快就只能获取单词

是否有可能在swift中这样做?

5 个答案:

答案 0 :(得分:33)

现在使用正则表达式,Swift非常丑陋 - 我们希望很快能获得更多原生支持!您想要的NSRegularExpression上的方法是matchesInString。以下是如何使用它:

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)
}

输出:

number of matches: 2
string
words

答案 1 :(得分:7)

如果要收集匹配的字符串,可以使用此选项。 (我的回答来自Nate Cooks非常有帮助的答案。)

针对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
    }
}

针对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
}}

答案 2 :(得分:4)

这个家伙怎么样,添加为String的扩展名? ))所有匹配,所有组)self = String如果你想不添加扩展名然后添加String参数并将所有self替换为你的参数:)

 func matchesForRegexInTextAll(regex: String!) -> [[String]] {

    do {
        let regex = try NSRegularExpression(pattern: regex, options: [])
        let nsString = self as NSString

        var resultsFinal = [[String]]()

        let results = regex.matchesInString(self,
            options: [], range: NSMakeRange(0, nsString.length))

        for result in results {
            var internalString = [String]()
            for var i = 0; i < result.numberOfRanges; ++i{
                internalString.append(nsString.substringWithRange(result.rangeAtIndex(i)))
            }
            resultsFinal.append(internalString)
        }

        return resultsFinal
    } catch let error as NSError {
        print("invalid regex: \(error.localizedDescription)")
        return []
    }
}

答案 3 :(得分:3)

所提供的所有答案都很好,但是我将提供用Swift 2.2编写的MSDN String扩展名。

注意到差异:

  • 仅使用第一场比赛
  • 支持多个已捕获的群组
  • 更准确的函数名称(它是捕获组,而不是匹配)

extension String {
    func capturedGroups(withRegex pattern: String) -> [String]? {
        var regex: NSRegularExpression
        do {
            regex = try NSRegularExpression(pattern: pattern, options: [])
        } catch {
            return nil
        }

        let matches = regex.matchesInString(self, options: [], range: NSRange(location:0, length: self.characters.count))

        guard let match = matches.first else { return nil }

        // Note: Index 1 is 1st capture group, 2 is 2nd, ..., while index 0 is full match which we don't use
        let lastRangeIndex = match.numberOfRanges - 1
        guard lastRangeIndex >= 1 else { return nil }

        var results = [String]()

        for i in 1...lastRangeIndex {
            let capturedGroupIndex = match.rangeAtIndex(i)
            let matchedString = (self as NSString).substringWithRange(capturedGroupIndex)
            results.append(matchedString)
        }

        return results
    }
}

使用:

// Will match "bcde"
"abcdefg".capturedGroups(withRegex: "a(.*)f")

答案 4 :(得分:1)

更新了Swift 4

/**
 String extension that extract the captured groups with a regex pattern

 - parameter pattern: regex pattern
 - Returns: captured groups
 */
public func capturedGroups(withRegex pattern: String) -> [String] {
    var results = [String]()

    var regex: NSRegularExpression
    do {
        regex = try NSRegularExpression(pattern: pattern, options: [])
    } catch {
        return results
    }
    let matches = regex.matches(in: self, options: [], range: NSRange(location:0, length: self.count))

    guard let match = matches.first else { return results }

    let lastRangeIndex = match.numberOfRanges - 1
    guard lastRangeIndex >= 1 else { return results }

    for i in 1...lastRangeIndex {
        let capturedGroupIndex = match.range(at: i)
        let matchedString = (self as NSString).substring(with: capturedGroupIndex)
        results.append(matchedString)
    }

    return results
}

使用:

// Will match "bcde"
"abcdefg".capturedGroups(withRegex: "a(.*)f")

Github上的要点:https://gist.github.com/unshapedesign/1b95f78d7f74241f706f346aed5384ff