Вопрос № 1 практически отвечает сам.Фактически, это пример из двух основных причин, по которым во многих случаях следует избегать регулярных выражений.
Вы унаследовали регулярное выражение, которое сработало, но теперь его нужно настроить, и никтов вашем магазине есть необходимые знания.
Данные имеют рекурсивную или иерархическую структуру, для которой регулярные выражения особенно плохо подходят.
Ваше регулярное выражение обходит проблему рекурсии путем обмана;он использует длину начального пробела каждой строки, чтобы определить, какой разделитель идет с каким.Вы могли бы сделать это правильно, используя функцию рекурсивного сопоставления .NET, но это было бы очень, очень уродливо.Итак, давайте посмотрим, что мы можем сделать с тем, что у вас есть.
@"^\t\[""([\s\S]*?)""] = {([\s\S]*?)^\t},$"
Ваша проблема с производительностью почти наверняка связана с той секундой [\s\S]*?
- которая, кстати, должна быть .*?
сОднолинейный режим;только JavaScript требует взлома [\s\S]
.Но каким бы способом вы это ни написали, вы просите сделать слишком много работы.Вот как я бы это сделал:
@"^\t\[""([^""]*)""\] *= *{(?>.*\n)*?\t}," // Multiline ON, Singleline OFF
Если вы сопоставляете один символ за раз с [\s\S]*?
, я сопоставляю всю строку за раз с (?>.*\n)*?
.Неохотные квантификаторы очень удобны, но вы можете столкнуться с такими же проблемами, как и с жадными, если переутомитесь с ними.
Я все еще использую якорь ^
в начале, но я нене нужно использовать якоря где-либо еще, потому что я явно сопоставляю все переводы строк.И хотя я использовал \n
в этом примере для ясности, я обычно использую (?:\r\n|[\r\n])
, чтобы соответствовать любому из трех наиболее распространенных разделителей строк: \r\n
(Windows), \r
(старые Mac) и \n
(Unix / Linux / OSX).