Подтвердить что ты не робот

Как сгруппировать поисковые выражения с помощью swift

В регулярных выражениях вы можете группировать разные совпадения, чтобы легко "сопоставить шаблон" с заданным совпадением.

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

Вышеуказанные работы обнаруживают, что они нашли диапазон совпадений, но он не может сказать мне группу. Например, если я ищу слова, инкапсулированные в ", я хотел бы совместить" слово", но быстро извлекал только слово

Можно ли сделать это быстрым?

4b9b3361

Ответ 1

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

Ответ 2

Вы можете использовать это, если хотите собрать соответствующие строки. (Мой ответ получен из очень полезного ответа 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
}}

Ответ 3

как насчет этих парней, добавьте как расширение для 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 []
    }
}

Ответ 4

Все предоставленные ответы хороши, но тем не менее я собираюсь предоставить мое расширение String, написанное в Swift 2.2.

Отмеченные отличия:

  • используйте только первое совпадение
  • поддерживает несколько захваченных групп
  • более точное имя функции (это группы захвата, а не совпадения)

.

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

Ответ 5

Обновлено для 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")

Gist on github: https://gist.github.com/unshapedesign/1b95f78d7f74241f706f346aed5384ff