Swift: Регулярный поиск для цикла не выполняется - PullRequest
1 голос
/ 18 марта 2019

Я выполняю поиск по регулярному выражению внутри цикла, но моя реализация, похоже, застряла, т.е. поиск не переходит к следующему циклу.

//At a function where I'm performing my regex search
let pattern = "([a-zA-Z0-9\\-\\_]*)*[sS]uper([a-zA-Z0-9\\-\\_]*)*"

for text in array {
    let matches = listMatches(for: pattern, inString: text)
    print(matches)

}

print("Regex done") //When a break point is placed here, this never gets executed

func listMatches(for pattern: String, inString string: String) -> [String] {
    guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
        return []
    }

    let range = NSRange(string.startIndex..., in: string)
    let matches = regex.matches(in: string, options: [], range: range)

    return matches.map {
        let range = Range($0.range, in: string)!
        return String(string[range])
    }
}

У меня около 5 текстов внутри array, а print(matches) напечатает около 3 matches. Цикл for никогда не проходит 4-й или 5-й цикл, а print("Regex done") никогда не выполняется. Размер text обычно составляет около 1000 символов. Любой совет, пожалуйста?

1 Ответ

1 голос
/ 19 марта 2019

Шаблон ([a-zA-Z0-9\-\_]*)*[sS]uper([a-zA-Z0-9\-\_]*)*, который вы используете, очень неэффективен и чреват катастрофическим возвратом .Когда вы помещаете образец неограниченной длины (например, a+ или a*) внутри группы и устанавливаете для него неограниченный квантификатор (например, (a+)+) и , шаблон не находится в концеregex, катастрофическое возвращение неизбежно со строками, которые соответствуют шаблону частично, но не полностью.

См. демонстрацию вашего шаблона , работающую с короткой строкой, такой как Super.Посмотрите, как трудно для движка регулярных выражений убедиться, что Super является правильным соответствием для шаблона, с красными стрелками, указывающими на возврат:

enter image description here

Теперь проверьте, насколько быстрым становится шаблон, если развернуть вложенные количественные шаблоны и использовать [a-zA-Z0-9_-]*[sS]uper[a-zA-Z0-9_-]*, см. эту демонстрацию , с количеством шагов, уменьшенным с 167 до 13. Обратите внимание, что вы этого не делаетевам нужно экранировать _ char (это word char), и вам не нужно экранировать - внутри класса символов, если он находится в начале / конце класса.

Если вы используете .caseInsensitive параметр (например, options: [ .caseInsensitive ]), вы можете даже сократить шаблон до [a-z0-9_-]*super[a-z0-9_-]*.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...