Найти - Пользователи
Полная версия: Регулярные выражения
Начало » Python для экспертов » Регулярные выражения
1 2
knkd
У меня есть данные в фомате “Ключ = значение”, записаны в строку через пробелы, количество пролов между элементами зависит только от фазы луны.
Моя задача - получить в список все значения.
import re
raw = ' x=-125.789 y = .125E+5 z= 25. w = -.254E-5'
pat = '(?<==)\s*[+-E\d\.]+'
re.findall(pat, raw)
...
['-125.789', ' .125E+5', ' 25.', ' -.254E-5']
Проблема в том что значения получаются со всеми пробелами между знаком “=” и числом.
Можно конечно так:
import re
raw = ' x=-125.789 y = .125E+5 z= 25. w = -.254E-5'
pat = '(?<==)\s*[+-E\d\.]+'
[x.strip() for x in re.findall(pat, raw)]
...
['-125.789', '.125E+5', '25.', '-.254E-5']
Но хотелось бы сделать только регулярными выражениями :)
Такая вот попытка заканчивается неудачей:
import re
raw = ' x=-125.789 y = .125E+5 z= 25. w = -.254E-5'
pat = '(?<==\s*)[+-E\d\.]+'
re.findall(pat, raw)
...
error: look-behind requires fixed-width pattern
Получается что неизвестное количество пробелов включить в подобное условие нельзя?

А выделить в список сразу и ключи и значения без комбинации сплита и стрипа вообще не получается :(

Это всё возможно?
pasaranax
pat = '(?<==)\s*([+-E\d\.]+)'
волшебные скобочки )
knkd
pasaranax
pat = '(?<==)\s*([+-E\d\.]+)'
волшебные скобочки )
хм. Работает. А в чём дело?
pasaranax
Скобки обособляют часть выражения. Вообще, у меня случайно получилось, я не думал, что re.findall будет выводить только обособленные скобками выражения. Если выделить несколько частей в скобки, то будет возвращен кортеж из этих выражений, таким образом можно выделить кроме значений еще и имена ключей.
pat = '\s*(\w*)\s*=\s*([+-E\d\.]+)'
если, конечно, \w* соответствует всем именам ключей
knkd
pasaranax
Вообще, у меня случайно получилось, я не думал, что re.findall будет выводить только обособленные скобками выражения.
Вот ведь как бывет :)

В (Россуме|Откидаче) написано что выражение в скобках образует группу на которую можно ссылаться, но что выводится только та часть которая соответствует группам - такого нет. Новее книг нету… :(

В свете такого открытия получается что данная конструкция «(?<==)» в «(?<==)\s*(+)» полностью бессмысленна? Поскольку соответствует «=\s*(+)».

pat = '\s*(\w*)\s*=\s*([+-E\d\.]+)'
Ну тогда получается что «\s*» - совершенно лишняя, поскольку «\w» и так соответствует слову.
Теперь остаётся понять чем «\w» отличается от «\w*».

Тоесть, с превращением в словарь и приведением чисел в каноничный вид, получается:
raw    = """  x=-125.789  comment1  y    = .125E+5 z=  25. comment2  w = -.254E-5  d45 =123.e-2"""
regexp = "(\w*)\s*=\s*([+-eE\d\.]+)"

print dict((x[0], str(float(x[1]))) for x in re.findall(regexp, raw))
...
{'y': '12500.0', 'x': '-125.789', 'z': '25.0', 'd45': '1.23', 'w': '-2.54e-06'}
Вот, только со вчерашнего утра решился наконец взяться за регулярные выражения и уже сколько открытий :D
pasaranax
\w соответствует одному символу, а \w* соответствует 0-inf символам. И, пожалуй \w* стоит заменить на \w+, чтобы не получалось, что ключа может и не быть. А минус внутри квадратных скобок желательно тоже экранировать, потому что он там является спецсимволом, указывающим на диапазон (например, ), и будь он не справа от плюса, получилась бы ошибка.
knkd
pasaranax
\w соответствует одному символу, а \w* соответствует 0-inf символам.
А я по описанию почему-то понял что \w соответствует всему слову :(

pasaranax
А минус внутри квадратных скобок желательно тоже экранировать, потому что он там является спецсимволом, указывающим на диапазон (например, ), и будь он не справа от плюса, получилась бы ошибка.
До такой ошибки я уже доэкстпериментировался :)

А вот ещё вопрос: Если данные необходимо разбить на секции по какому-нибудь признаку.
raw    = """section  x=-125.789   y    = .125E+5 z=  25.  section  w = -.254E-5  d45 =123.e-2"""
... "Должно получится"
[[('x', '-125.789'), ('y', '.125E+5')], [('w', '-.254E-5'), ('d45', '123.e-2')]]
Объединение в группу всего выражения «section\s*((\w+)\s*=\s*(+))*» даёт плохие результаты.
pasaranax
Это уже слишком сложно, тут нужно в 2 прохода - сначала секции выделить, а потом то, что выше делали, в каждой секции.
knkd
pasaranax
тут нужно в 2 прохода
Эхх. А так хотелось :)
straton
есть фрагмент кода:

temp = re.findall("[(.*),", text)
однако при попытке выполнения этого вылезает ошибка:
“unexpected end of regular expression” (переводить не надо, я и так знаю)
подскажите, в чем дело?
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