Как можно идентифицировать и хранить переменные и данные из отформатированного текстового файла в Python 3.x? - PullRequest
0 голосов
/ 01 июня 2018

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

<THING1> \ 
 var1         =  0        \#
   var2      = "0.0 100.0 0.0"          \#
var3     = "IDENTIFYING_WORD"      \#
var4      = 2                 \#
</THING1>

<THING2> \
 # something similar
</THING2>

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

with open('data.txt', 'r') as f:
    content  = f.read()
    t1start  = content.find('<THING1>')
    t1end = content.find('</THING1>')
    t1 = content[t1start:t1end]
    f.close

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

i1 = t1.index('\n')
i2 = t1[i1+1:].index('\n')
line1 = t1[i1:i2]

, но это не совсем то, что я хочу.

В идеале я хотел бы, чтобы данные сохранялись в Python как

var1 = 0
var2 = [0, 100, 0]
var3 = "IDENTIFYING_WORD"
var4 = 2

, где var1 и var 4 - это целые числа, var2 - это массив, а var3 - это строка.У кого-нибудь есть мысли по этому поводу?Я пытался искать в другом месте в стеке, но ничего не могу найти.Если на этот вопрос ответили, пожалуйста, направьте меня в правильном направлении, и я сниму это.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Может быть, вы можете использовать регулярные выражения следующим образом:

import re

def get_value(y):
    if 'var1' in y or 'var3' in y or 'var4' in y:
        return_value = y.split('=')[1].strip()
        try:
            return int(return_value)
        except ValueError:
            return return_value
    elif 'var2' in y:
        return_value = y.split('=')[1].strip().split(" ")
        return [float(i.replace('"','')) for i in return_value]


string = """
<THING1> \ 
 var1         =  0        \#
   var2      = "0.0 100.0 0.0"          \#
var3     = "IDENTIFYING_WORD"      \#
var4      = 2                 \#
</THING1>

<THING2> \
 var1         =  5        \#
   var2      = "0.0 100.0 0.0"          \#
var3     = "IDENTIFYING_WORD"      \#
var4      = 7                 \#
</THING2>
"""



pat = re.compile(r'<THING\d>(.*?)</THING\d>')
x = re.findall(pat, string.replace('\n',''))
mainlist = [['var1','var2','var3','var4']]
for i in x:
    mylist = []
    for j in i.split(r'\#'):
        if j.strip() != '':
            mylist.append(get_value(j))
    mainlist.append(mylist)
print(mainlist)

Результат:

[
    ['var1', 'var2', 'var3', 'var4'], 
    [0, [0.0, 100.0, 0.0], '"IDENTIFYING_WORD"', 2], 
    [5, [0.0, 100.0, 0.0], '"IDENTIFYING_WORD"', 7]
]
0 голосов
/ 01 июня 2018

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

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

После того, как вы установили пип lark-parser, попробуйте этот фрагмент:

import sys
import textwrap
from lark import Lark

if __name__ == "__main__":
    content = textwrap.dedent(r"""

    <THING1> \
     var1         =  0        \#
       var2      = "0.0 100.0 0.0"          \#
    var3     = "IDENTIFYING_WORD"      \#
     # something similar
    var4      = 2                 \#
    </THING1>

    <THING2> \
     # something similar
     var1         =  0        \#
    </THING2>

    """)

    grammar = r"""
        ?start: block*
        block:  tag_start line* tag_end
        tag_start: "<" NAME ">" "\\"
        tag_end: "</" NAME ">"
        line: assignment
            | comment
        assignment: lhs "=" rhs "\#"
        comment: "#" NAME* NEWLINE
        lhs: NAME
        rhs: ESCAPED_STRING
            | NAME
            | NUMBER

        %import common.NEWLINE
        %import common.ESCAPED_STRING
        %import common.CNAME -> NAME
        %import common.NUMBER
        %import common.WS

        %ignore WS
    """

    parser = Lark(grammar)
    tree = parser.parse(content)

    for block in tree.find_data("block"):
        tag_name = list(block.find_data("tag_start"))[0].children[0]
        print(tag_name.center(80, '-'))
        for assignment in block.find_data("assignment"):
            var_name = assignment.children[0].children[0]
            value = assignment.children[1].children[0]
            print(var_name, "=>", value)

Вы должны получить что-то вроде этого:

-------------------------------------THING1-------------------------------------
var1 => 0
var2 => "0.0 100.0 0.0"
var3 => "IDENTIFYING_WORD"
var4 => 2
-------------------------------------THING2-------------------------------------
var1 => 0

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

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