Использование Regex в Python для получения размеров массива

Я очень, очень новичок в регулярных выражениях. Я только что поднял его около 3 часов назад, но я ударил оцепление, и я не могу пошатнуть его. Поэтому, как всегда, я обратился к Интернету, чтобы решить все мои проблемы, и когда он не смог объяснить ответы на мои вопросы, я искал в stackoverflow, чтобы узнать, спросил ли кто-то другой мой вопрос, и, наконец, только что опубликовал новый вопрос, когда Я сам не мог ответить на него.

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

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

Variable | (Variable)
Variable.list[3]name | (Variable.list[3]name)
Var.list[5] | (Var.list , 5)
Var.list_name[3]thing_words[4][3][2] | (Var.list_name[3]thing_words , 4 , 3 , 2)
Var[3] | (Var , 3)
Var.word | (Var.word)

И так далее. Я думаю, что это ясно, верно? Я хочу, чтобы имя переменной, которая может содержать или не содержать скобки, и если есть какие-либо конечные скобки, я хочу исключить их из имени и захватить их, чтобы я мог получить к ним доступ из match.groups(). Я не думаю, что есть какая-либо переменная с именем, которое заканчивается... [] без номера внутри, но может быть, и если есть, я тоже хочу игнорировать их.

Прямо сейчас я пытаюсь сделать что-то вроде:

for line in list:
regex = re.compile("^[-\w\[\]\.]+(\[(0-9)*]\])*$")
match = regex.match(line)
if match:
do something that depends on len( match.groups() )

Но... это не работает. Регулярное выражение никогда не совпадает, даже если я думаю, что это нужно.

На мой взгляд, я очень ясен! Я хочу, чтобы он начинался с кучу вещей и, возможно, заканчивался кучей номеров в скобках, и если он заканчивается заключенными в квадратные скобки номерами, чтобы поймать их и сохранить их, но игнорировать любые скобки, которые НЕ находятся в конце строки.

Итак... теперь, когда я полностью передумал, я объяснил себе, что я немного избыточен... что я делаю, чтобы заставить его работать так, как я хочу? Может ли это быть сделано так, как я пытаюсь это сделать? Должен ли я вместо этого делать что-то большее:

while (match.endswith("]")
match.strip("]")
func()
match.strip("[")

где func() выполняет регулярное выражение, чтобы удалить число с конца? Это кажется слишком сложным и очень грязным. Моя кишка говорит мне, что регулярное выражение может справиться с этим, и мои новички просто не видят, как это сделать.

2 ответа

Эта проблема немного сложнее, чем я понял, потому что модуль re не позволяет повторять группы захвата, поэтому вам нужно будет выполнить ручную работу, чтобы дифференцировать. Во-первых, используйте одно регулярное выражение для разделения строки в нужном месте; затем используйте другой, чтобы найти все числа.

def get_variable_and_sizes(var_string):
 result = re.search(r'(.*?)((?:\[\d*])*)$', var_string)
 var_name = result.group(1)
 numbers = re.findall(r'\[(\d+)]', result.group(2))
 return [var_name] + numbers

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

Первая группа в матче, который мы получаем, - это имя переменной. Вторая группа должна быть проанализирована далее, чтобы идентифицировать все числа в ней. К счастью, легко написать регулярное выражение, которое фиксирует число внутри скобок, а затем использовать findall для получения списка всех совпадений во второй группе. Если таких совпадений нет, мы получаем пустой список.

Наконец, мы создаем список, содержащий имя переменной, объединяем список, который мы получили от второго регулярного выражения, и возвращаем его.


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

^[a-zA-Z\.]+(?:\[\d\][a-zA-Z\.]+)*(?:\[(\d)\])?(?:\[(\d)\])?(?:\[(\d)\])?(?:\[(\d)\])?$

это регулярное выражение будет захватывать до 4 квадратных групп в конце строки.

Кроме этого. Я думаю, что парсер будет вашим лучшим вариантом.

licensed under cc by-sa 3.0 with attribution.