2015-11-05 2 views
0

Я хочу совместить линию локализации с регулярным выражением. Все работает отлично, если не пытаться сопоставить эту строку. Вы можете поместить код на игровой площадке, чтобы увидеть, что он не останавливается, или в пустом проекте, чтобы увидеть, что процессор будет 100% и застрял на линии «let match». Теперь интересно, если вы удалите последнее слово, которое оно работает. Я не знаю, работает ли с китайскими или другими странными символами, это греческий.Swift и регулярное выражение, cpu идет haywire для некоторых строк

let lineContent = "\"key\" = \" Χρήση παλιάς συνόμευση\";" 
if let r = try? NSRegularExpression(pattern: "\"(.*)+\"(^|[ ]*)=(^|[ ]*)\"(.*)+\";", options: NSRegularExpressionOptions()) { 
    let match = r.matchesInString(lineContent, options: NSMatchingOptions(), range: NSMakeRange(0, lineContent.characters.count)) 
    match.count 
} 

Позже изменения: это на самом деле не имеет значения, символы типа, но количество слов. Эта строка положить в правой стороне тоже не работает: «JHG jhgjklkhjkh HHHHH HHH»

+1

Я думаю, что часть проблемы является первым '+' (. *) - как это будет захватывать все впереди. Попробуйте сделать это ленивым: '(. *?)'. – sideroxylon

+0

Вы действительно хотите использовать регулярное выражение для этого? Кажется, что простой парсер будет делать и будет намного эффективнее. – Kametrixom

+2

У вас есть вложенные кванторы в '(. *) +', Что приведет к [катастрофическому обратному отскоку] (http://www.regular-expressions.info/catastrophic.html).Возможно, что-то вроде '' \ '([^ \ "] *) \" [] * = [] * \ "([^ \"] *) \ ";" ' – Mariano

ответ

2

У вас есть вложенные кванторы в (.*)+, которые приведут к catastrophic backtracking (рекомендую прочитать эту статью). Проблема заключается в том, когда сбой подвыражения завершается неудачей, двигатель regex отступает, чтобы проверить другую альтернативу. Наличие вложенных квантификаторов означает, что для каждого символа в строке объекта будет экспоненциальное число попыток: он будет проверять все повторения (.*)+ и, для каждого, также все повторения .*.

Чтобы избежать этого, используйте шаблон, определенный как конкретные, как вы можете:

"\"([^\"]+)\"[ ]*=[ ]*\"([^\"]*)\";" 
  • \"([^\"]+)\" соответствий
    • Открытие "
    • [^\"]+ Любое количество символов, кроме кавычек. Измените + на *, чтобы разрешить пустые строки.
    • замыкающего "

Код

let lineContent = "\"key\" = \" Χρήση παλιάς συνόμευση\";" 
if let r = try? NSRegularExpression(pattern: "\"([^\"]+)\"[ ]*=[ ]*\"([^\"]*)\";", options: NSRegularExpressionOptions()) { 
    let match = r.matchesInString(
     lineContent, 
     options: NSMatchingOptions(), 
     range: NSMakeRange(0, lineContent.characters.count) 
    ) 

    for index in 1..<match[0].numberOfRanges { 
     print((lineContent as NSString).substringWithRange(match[0].rangeAtIndex(index))) 
    } 
} 

SwiftStub demo

+0

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

+0

Я изменил '*' на '+', чтобы потребовать левую строку – Mariano

1

Как уже упоминался в комментариях .*+ вызывает катастрофические откаты, вызывая высокую загрузку процессора (и, в общем, неспособность соответствовать) ,

Вместо того, чтобы использовать шаблон, как

\"(.*)+\" 

так, вы все соответствия между двойными кавычками, использовать отрицание набора символов:

\"([^\"]+)\" 
1

В соответствии с комментарием выше - заменить вложенный (.*)+ с ленивой версией - (.*?).

Смежные вопросы