Пара вариаций на твою тему. Во-первых, я всегда считал, что регулярное выражение является загадочным до неустранимого, поэтому я написал модуль pyparsing. Я мысленно смотрю на ваш код и думаю: «О, это список строк, разделенных символом« / », знак« = », а затем какое-то значение». И это довольно прямо переводится в код определения синтаксического анализатора. Добавляя имя здесь и там в анализаторе («ключ» и «значение», аналогично именованным группам в регулярном выражении), вывод довольно легко обрабатывается.
data="""\
Same/Same2/Foot/Ankle/Joint/Actuator/Sensor/Temperature/Value=4.123
Same/Same2/Battery/Name=SomeString
Same/Same2/Home/Land/Some/More/Stuff=0.34""".splitlines()
from pyparsing import Word, alphas, alphanums, Word, nums, QuotedString, delimitedList
wd = Word(alphas, alphanums)
number = Word(nums+'+-', nums+'.').setParseAction(lambda t:float(t[0]))
rvalue = wd | number | QuotedString('"')
defn = delimitedList(wd, '/')('key') + '=' + rvalue('value')
for d in data:
result = defn.parseString(d)
Во-вторых, я подвергаю сомнению ваш подход к определению всех этих имен переменных - создание имен переменных на лету на основе ваших данных является довольно хорошо узнаваемым запахом кода (не обязательно плохим, но вы могли бы действительно хочу переосмыслить этот подход). Я использовал рекурсивный defaultdict, чтобы создать навигационную структуру, чтобы вы могли легко выполнять такие операции, как «найти все записи, которые являются подэлементами« Same2 »(в данном случае« Foot »,« Battery »и« Home ») - этот вид работы более сложен, когда вы пытаетесь отобрать некоторую коллекцию имен переменных, как это найдено в locals (), мне кажется, вам придется в конце концов анализировать эти имена, чтобы восстановить иерархию ключей.
from collections import defaultdict
class recursivedefaultdict(defaultdict):
def __init__(self, attrFactory=int):
self.default_factory = lambda : type(self)(attrFactory)
self._attrFactory = attrFactory
def __getattr__(self, attr):
newval = self._attrFactory()
setattr(self, attr, newval)
return newval
table = recursivedefaultdict()
# parse each entry, and accumulate into hierarchical dict
for d in data:
# use pyparsing parser, gives us key (list of names) and value
result = defn.parseString(d)
t = table
for k in result.key[:-1]:
t = t[k]
t[result.key[-1]] = result.value
# recursive method to iterate over hierarchical dict
def showTable(t, indent=''):
for k,v in t.items():
print indent+k,
if isinstance(v,dict):
print
showTable(v, indent+' ')
else:
print v
showTable(table)
Печать:
Same
Same2
Foot
Ankle
Joint
Actuator
Sensor
Temperature
Value 4.123
Battery
Name SomeString
Home
Land
Some
More
Stuff 0.34
Если вы действительно настроены на определение этих имен переменных, то добавление некоторых полезных действий разбора в pyparsing переформатирует проанализированные данные во время разбора, чтобы впоследствии их можно было непосредственно обработать:
wd = Word(alphas, alphanums)
number = Word(nums+'+-', nums+'.').setParseAction(lambda t:float(t[0]))
rvaluewd = wd.copy().setParseAction(lambda t: '"%s"' % t[0])
rvalue = rvaluewd | number | QuotedString('"')
defn = delimitedList(wd, '/')('key') + '=' + rvalue('value')
def joinNamesWithAllCaps(tokens):
tokens["key"] = '_'.join(map(str.upper, tokens.key))
defn.setParseAction(joinNamesWithAllCaps)
for d in data:
result = defn.parseString(d)
print result.key,'=', result.value
Печать:
SAME_SAME2_FOOT_ANKLE_JOINT_ACTUATOR_SENSOR_TEMPERATURE_VALUE = 4.123
SAME_SAME2_BATTERY_NAME = "SomeString"
SAME_SAME2_HOME_LAND_SOME_MORE_STUFF = 0.34
(Обратите внимание, что это также заключает ваше значение SomeString в кавычки, так что результирующий оператор присваивания является допустимым Python.)