Разобрать пользовательский файл в C # - PullRequest
1 голос
/ 26 июня 2010
  1. Должен ли я использовать RegularExpressions для этого?
  2. Можно структурировать результаты как запросные, IEnumerable и т. Д.

У меня есть файл, я не могу изменитькак это генерируется.Я хочу создать класс парсера для извлечения всех данных.В идеале я хотел бы использовать этот класс, чтобы открыть файл и вернуть ему запрашиваемую структуру типа массива, которую я могу использовать.

Данные структурированы следующим образом:

["Table"] = {
    ["Text"] = { 
        ["Number"] = { 
            "Item", --[1]
            "Item", --[2]
            "Item", --[3]
        },
    --repeat--
Note that the actual file has line brakes, tab, etc. (\n\t\t) 
As you will see the patters I use take this into account 
to get different levels.

У меня есть регулярное выражение, написанное для vb6 для этого самого файла, но 1 из 7 шаблонов не работает:

@"^\t\[""([\s\S]*?)""] = {([\s\S]*?)^\t},$

Это должно сгруппировать самый верхний уровень ["Таблица"] в их собственное соответствие.но он возвращает 0 и это медленно.Если я возьму знак $, он тоже вернет все подузлы.Это единственное, что мешает мне использовать Регулярные выражения для этого.

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

Есть мысли?

Ответы [ 5 ]

3 голосов
/ 26 июня 2010

Я бы держался подальше от Регулярных выражений, если вы захотите выполнить какой-либо реальный анализ такого файла, вы быстро столкнетесь с огромными проблемами, которые невозможно отладить с помощью Regex, например, решив правильную вложенность (если ваш файл может иметь несколько уровни вложенности) и правильность причинят вам столько головной боли. Есть много шаблонов, которые могут заставить любой процессор регулярных выражений выглядеть почти как бесконечный цикл и никогда не заканчиваться (или, по крайней мере, не в любое разумное время), и на самом деле написание таких простых анализаторов должно быть быстрым и приводить к лучшей отладке, производительности, удобству обслуживания и т. д.

1 голос
/ 26 июня 2010

Я предполагаю, что ваша структура связана с Lua.По крайней мере, по внешнему виду, который Луа должен прочитать каждый день.Если я прав, вы, возможно, захотите проверить luainterface

Также есть несколько других вопросов с примером кода: Анализ структуры данных Lua , Чтение вложенныхЛуа стол

1 голос
/ 26 июня 2010

Иди со своей интуицией. Регулярные выражения - правильный способ справиться с этим. Если бы вы могли опубликовать образец, я могу помочь вам написать RegEx, чтобы соответствовать, что вы хотите: -)

Один из способов быстрого тестирования регулярных выражений - перейти к http://rubular.com/

Он показывает вам совпадения с вашим образцом на лету .. позволяя вам быстро настроить выражение лица.

0 голосов
/ 26 июня 2010

Вопрос № 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).

0 голосов
/ 26 июня 2010

Не используйте Regex - получите правильный синтаксический анализатор, который вы можете поместить в файл синтаксиса. Это позволяет намного более сложный анализ по сравнению с REGEX.

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