Найти - Пользователи
Полная версия: Помогите допилить регулярное выражение
Начало » Python для новичков » Помогите допилить регулярное выражение
1
lizzard
Привет всем.

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

Дана строка вида “(A,B,C),(D,E,F)”. Необходимо получить список строк “(A,B,C)”, “(D,E,F)”. Или без скобок, не принципиально. Сам я написал для этого что-то вроде этого:
re.compile(r"(\(.*?\)),{0,1}").findall(s)
И множество “вариаций на тему” :). Для указанного примера “как есть” всё работает, но проблемы возникнут если если одна из переменных в скобках будет строковой и будет содержать скобки (строковые переменные заключены в одинарные кавычки, следовательно в них ещё и кавычки экранируются, если встречаются). Пример:
>>> c = """(1,2,'3'),(1,2,'asd(asd)asd')"""
>>> re.compile(r"(\(.*?\)),{0,1}").findall(c)
["(1,2,'3')", "(1,2,'asd(asd)"]
А хотелось бы получить список . Никак не соображу что подправить надо, подскажите плиз %).
dimabest
import re

c = """(1,2,'3'),(1,2,'asd(asd)asd')"""

print re.split('(?<=\)),(?=\()', c)
результат:
["(1,2,'3')", "(1,2,'asd(asd)asd')"]
Твоя регулярка не работает по той простой причине, что в строке есть вложенные скобки.
lizzard
dimabest
Спасибо большое, твой вариант работает… пока не разобрался как, но работает :D. Но это уже сам в доках почитаю.
Rodegast
Да тут и без регулярок можно обойтись:
>>> c = """(1,2,'3'),(1,2,'asd(asd)asd')"""
>>> c = c.split("),(")
>>> c[0] = c[0][1:]
>>> c[-1] = c[-1][:-1]
>>> c
["1,2,'3'", "1,2,'asd(asd)asd'"]
lizzard
Rodegast, спасибо за ответ.

Кстати оба примера могут засыпаться на таком:
>>> c = """(1,2,'3),(')"""
>>> c.split("),(")
["(1,2,'3", "')"]
>>> re.compile(r"(\(.*?\)),{0,1}").findall(c)
["(1,2,'3)", "(')"]
Но я надеюсь таких данных не встретится, решение всё же нужно было больше для себя :).
Rodegast
Вы просто не внимательно смотрели код : ) После разбития строки на список в первом и последнем элементе остаются остатки от скобок. Они и удаляются следующими двумя строками.
lizzard
Rodegast
Не, я просто невнимательно привёл результат, извиняюсь)). Проблема не в “лишних” скобках, а в количестве подстрок, которое мы получим (2, а должна быть одна). Так наглядней будет:
>>> c = """(1,2,'3),(')"""
>>> c.split("),(")
["(1,2,'3", "')"]
>>> [_[0][1:], _[-1][:-1]]
["1,2,'3", "'"] # а хотелось бы получить ["1,2,'3),('"]
lizzard
Попробую описать всё ещё раз и полностью :). Необходимо выдернуть из строки все N (N >= 1) блоков значений. Блоки значений заключены в скобки и разделены запятыми. Содержание блоков - значения через запятую. Значения могут быть цифрами или строками. Строковые значения заключены в одинарные кавычки. Одинарные и двойные кавычки в строковых значениях экранируются. Одиночные слэши экранируются. Как-то так…

Вот мой велосипед, если кому интересно, но хотелось сделать красивей, поэтому начал с регулярок :)
def process_values(values):
not_quoted = True
not_escaped = True
prev_position = 0
for i in xrange(len(values)):
if values[i] == ')' and not_quoted:
yield values[prev_position:i+1]
prev_position = i
elif values[i] == "'" and not_escaped:
not_quoted ^= True
elif values[i] == '(' and not_quoted:
prev_position = i
elif values[i] == '\\':
not_escaped ^= True
elif values[i] == "'" or values[i] == '"' \
or values[i] == 'r' or values[i] == 'n' \
and not not_escaped:
not_escaped = True

c = r"""(1,2,'\'3\\'),(1,2,'),('),(1,2,'\"3\\')"""
for val in process_values(c):
print val
Результат в порядке:
(1,2,'\'3\\')
(1,2,'),(')
(1,2,'\"3\\')
Griffon
Первое что пришло в голову:
# py31
print(list(str(x) for x in eval(a)))
upd: где А - наша строка.
lizzard
Griffon, гениально :D
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB