Я предлагаю использовать парсер, который способен обрабатывать такие структуры. Регулярное выражение терпит неудачу, и это правильно, поскольку язык, который вы пытаетесь проанализировать, не выглядит регулярным - по крайней мере из приведенных выше примеров. Всякий раз, когда вам нужно распознать вложение, регулярные выражения либо потерпят неудачу, либо превратятся в сложных зверей, подобных приведенному выше. Даже если язык регулярный, это регулярное выражение там выглядит слишком сложным для меня. Я бы лучше использовал что-то вроде этого:
def parse_String(string):
index = skip_spaces(string, 0)
index, prefix = read_prefix(string, index)
index = skip_spaces(string, index)
index, attrgroup = read_attrgroup(string, index)
index = skip_spaces(string, index)
index, suffix = read_suffix(string, index)
return prefix, attrgroup, suffix
def read_prefix(string, start_index):
return read_quoted_string(string, start_index)
def read_attrgroup(string, start_index):
end_index, content = read_paren(string, start_index)
index = skip_spaces(content, 0)
index, first_entry = read_quoted_string(content, index)
index = skip_spaces(content, index)
index, second_entry = read_quoted_string(content, index)
return end_index, (first_entry, second_entry)
def read_suffix(string, start_index):
return read_quoted_string(string, start_index)
def read_paren(string, start_index):
return read_delimited_string(string, start_index, '(', ')')
def read_quoted_string(string, start_index):
return read_delimited_string(string, start_index, '"', '"')
def read_delimited_string(string, starting_index, start_limiter, end_limiter):
assert string[starting_index] == start_limiter, (start_limiter
+"!="
+string[starting_index])
current_index = starting_index+1
content = ""
while(string[current_index] != end_limiter):
content += string[current_index]
current_index += 1
assert string[current_index] == end_limiter
return current_index+1, content
def skip_spaces(string, index):
while string[index] == " ":
index += 1
return index
да, это больше кода, и да, по необработанному количеству ключей, это заняло больше времени. Однако, по крайней мере для меня, мое решение гораздо проще проверить. Это увеличивается еще больше, если вы удаляете кучу строк-и-индексов, перемещая все это в класс, который анализирует такие строки в своем конструкторе. Кроме того, легко сделать пропущенный пробел неявным (используя некоторый волшебный метод next-char, который просто пропускает символы до тех пор, пока не появится пробел, если только он не находится в не пропущенном режиме из-за строк. Этот режим можно установить в функция с разделителями, например). Это превратит строку parse_string в:
def parse_string(string):
prefix = read_prefix()
attrgroup = read_attr_group()
suffix = read_suffix()
return prefix, attrgroup, suffix.
Кроме того, эти функции можно расширить, чтобы охватить более сложные выражения. Произвольно вложенные группы атрибутов? изменение одной строки кода. Вложенные парены? немного больше работы, но нет реальной проблемы.
А теперь, пожалуйста, подожди и опровергни меня за то, что я какой-то еретик-регулярник и какой-то сторонник парсера. >:)
PS: да, этот код не проверен. насколько я знаю, там 3 опечатки, которых я не видел.