2009-06-26 3 views
3

У меня есть файл, содержащий большое количество данных положить в форму, подобную этой:Синтаксический неизвестную структуру данных в Python

Group1 { 
    Entry1 { 
     Title1 [{Data1:Member1, Data2:Member2}] 
     Title2 [{Data3:Member3, Data4:Member4}] 
    } 
    Entry2 { 
     ... 
    } 
} 
Group2 { 
    DifferentEntry1 { 
     DiffTitle1 { 
      ... 
     } 
    } 
} 

Дело в том, я не знаю, сколько слоев скобок есть и как структурированы данные. Мне нужно изменить данные и удалить всю запись в зависимости от условий, связанных с членами данных, прежде чем записывать все в новый файл. Каков наилучший способ чтения в файле? Благодаря!

+0

Есть ли только корень? То есть, все будет в Group1 или это может быть что-то вроде Group1 { ... } группа_2 { ... } Если да, то может ли быть элементы, которые не являются группами. Группа1 { ... } Заголовок4 [{Hello: Bye}] – basaundi

+1

Существует несколько групп. Элементами являются все группы, но записи в каждой группе могут быть структурированы по-разному между группами. – Lin

+0

(1) Давайте посмотрим: структура данных неизвестна, вы не говорите, откуда вы получили данные, вы не говорите, почему вы не спросили источник данных о его структуре, вы указали только очень неопределенное описание «псевдоданных». Расскажите, пожалуйста, почему мы не должны беспокоиться о том, что «помощь» может быть истолкована федеральными властями как «пособничество и подстрекательство». (2) Вы уверены, что это не JSON или некоторые извращения? –

ответ

1

У меня есть нечто похожее, но написанное в java. Он анализирует файл с той же базовой структурой с немного отличающимся синтаксисом (no '{' и '}' только отступом, как в python). Это очень простой язык скриптов.

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

Я не хочу публиковать весь источник, потому что он большой, и он доступен в коде google (lizzard-entertainment, revision 405). Есть несколько вещей, которые вам нужно знать.

  • Инструкция является абстрактным классом и имеет block_expected метод, чтобы указать погоду бетон инструкция нуждается в блок (например, петли и т.д.) В вашем случае это не нужно вам нужно только проверить «{».
  • Блок расширяет Инструкцию. Он содержит список инструкций и добавляет метод добавления.
  • indent_level возвращает, сколько пробелов предшествует инструкциям. Это также необязательно с «{}» singns.

заполнителем

BufferedReader input = null; 
try { 
    input = new BufferedReader(new FileReader(inputFileName)); 
    // Stack of instruction blocks 
    Stack<Block> stack = new Stack<Block>(); 
    // Push the root block 
    stack.push(this.topLevelBlock); 
    String line = null; 
    Instruction prev = new Noop(); 
    while ((line = input.readLine()) != null) { 
     // Difference between the indentation of the previous and this line 
     // You do not need this you will be using {} to specify block boundaries 
     int level = indent_level(line) - stack.size(); 
     // Parse the line (returns an instruction object) 
     Instruction inst = Instruction.parse(line.trim().split(" +")); 
     // If the previous instruction expects a block (for example repeat) 
     if (prev.block_expected()) { 
      if (level != 1) { 
       // TODO handle error 
       continue; 
      } 
      // Push the previous instruction and add the current instruction 
      stack.push((Block)(prev)); 
      stack.peek().add(inst); 
     } else { 
      if (level > 0) { 
       // TODO handle error 
       continue; 
      } else if (level < 0) { 
       // Pop the stack at the end of blocks 
       for (int i = 0; i < -level; ++i) 
        stack.pop(); 
      } 
      stack.peek().add(inst); 
     } 
     prev = inst; 
    } 
} finally { 
    if (input != null) 
     input.close(); 
} 
+0

Отметьте свой код (есть кнопка на панели инструментов), чтобы он был правильно отформатирован. – Kiv

+0

Извините, это не работает для меня. По крайней мере, последняя часть видна сейчас. – stribika

+0

У вас есть список раньше, у которого есть собственный отступ. Либо введите что-то в незакрепленной строке между ними, либо еще больше отпустите код. –

1

Это зависит от того, как структурированы данные и какие изменения вам необходимы.

Один из вариантов может заключаться в том, чтобы разобрать это в структуру данных Python, похоже, что это похоже, за исключением того, что у вас нет кавычек вокруг строк. Это облегчает сложные манипуляции.

С другой стороны, если все, что вам нужно сделать, это внести изменения, которые изменяют некоторые записи в другие записи, вы можете сделать это с помощью поиска и замены.

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

+1

Я хочу удалить «запись» каждый раз, когда получаю что-то вроде «Data1: 0» или «Data: []». А также сортировать записи в каждой группе на основе других условий членов данных. Я буду рассматривать синтаксический анализ как структуру данных Python, хотя, спасибо! – Lin

+0

Да, если вы хотите отсортировать их, разбор в структуре Python определенно звучит как лучший. –

1

Это довольно схожая проблема с обработкой XML, и для этого существует много кода Python. Поэтому, если вы можете каким-то образом преобразовать файл в XML, вы можете просто запустить его через парсер из стандартной библиотеки. Версия XML вашего примера будет что-то вроде этого:

<group id="Group1"> 
    <entry id="Entry1"> 
     <title id="Title1"><data id="Data1">Member1</data> <data id="Data2">Member2</data></title> 
     <title id="Title2"><data id="Data3">Member3</data> <data id="Data4">Member4</data></title> 
    </entry> 
    <entry id="Entry2"> 
     ... 
    </entry> 
</group> 

Конечно, преобразование в XML, вероятно, не самая простая вещь, чтобы сделать. Но ваша работа очень похожа на то, что уже было сделано с синтаксическими анализаторами XML, у вас просто есть другой синтаксис для решения. Таким образом, вы можете взглянуть на некоторый код синтаксического анализа XML и написать небольшой парсер Python для вашего файла данных на основе этого. (В зависимости от того, как реализован XML-синтаксический анализатор, вы даже можете скопировать код, просто измените несколько регулярных выражений и запустите его для своего файла)

3

Структура данных в основном представляет собой диктовку, где ключи являются строками и значение либо строка, либо другой ДИКТ того же типа, так что я рекомендовал бы, возможно, потянув его в такую ​​структуру питона,

например:

{'group1': {'Entry2': {}, 'Entry1': {'Title1':{'Data4': 'Member4', 
'Data1': 'Member1','Data3': 'Member3', 'Data2': 'Member2'}, 
'Title2': {}}} 

на верхнем уровне файл, который вы создали бы пустой dict, а затем для каждой прочитанной строки вы используете идентификатор в качестве ключа, а затем, когда вы увидите {вы создаете v alue для этого ключа как dict. Когда вы видите «Key: Value», вместо того, чтобы создавать этот ключ как dict, вы просто вставляете значение обычно. Когда вы видите a}, вам нужно «вернуться назад» к предыдущему dict, над которым вы работали и возвращаетесь к заполнению этого.

Я бы подумал, что весь этот синтаксический анализатор помещает файл в структуру python, подобную этому может быть сделано в одной довольно короткой рекурсивной функции, которая просто называет себя, чтобы заполнить каждый поддиск, когда он увидел {, а затем вернулся к своему вызывающему абоненту при наблюдении}

2

Если у вас есть грамматика для структуры вашего файла данных , или вы можете создать его самостоятельно, вы можете использовать генератор синтаксического анализатора для Python, например YAPPS: link text.

3

Вот грамматика.

dict_content : NAME ':' NAME [ ',' dict_content ]? 
      | NAME '{' [ dict_content ]? '}' [ dict_content ]? 
      | NAME '[' [ list_content ]? ']' [ dict_content ]? 
      ; 

list_content : NAME [ ',' list_content ]? 
      | '{' [ dict_content ]? '}' [ ',' list_content ]? 
      | '[' [ list_content ]? ']' [ ',' list_content ]? 
      ; 

Верхний уровень dict_content.

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

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