Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 8, 2015 08:37:26

Dezex
Зарегистрирован: 2015-12-08
Сообщения: 16
Репутация: +  0  -
Профиль   Отправить e-mail  

re. выбрать данные из строки, в зависимости от предыдущей

Всем привет!
Не первый раз работаю с регулярными выражениями (правдо на автоите дело было).
Есть строки определенного вида:

titleA var1 r.text(a, b, <NAME>) var11
titleB var2 r.text(a, b, <ip_addr1>) var22
titleA var3 r.text(a, b, <name>) var33
titleB var4 r.text(a, b, <ip_addr2>) var44
Мне нужно получить значение <ip_addr>, если в предыдуще строке (где titleA)
нет параметра <NAME>. И я такой думаю, что тут нужно использовать (?: ) и re.findall:

import re
string = 'titleA var1 r.text(a, b, <NAME>) var11\ntitleB var2 r.text(a, b, <ip_addr1>) var22\ntitleA var3 r.text(a, b, <name>) var33\ntitleB var4 r.text(a, b, <ip_addr2>) var44'
t1 = re.findall('titleA[^(?:r.text)]*r\.text\([^\)]*[^(?:NAME)]*\)[^(?:r.text)]*r\.text\([^\)]*([1-9][0-9]{0,2}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\)',string,re.DOTALL)
print t1

И конечно же ничего не работает. Я попытался разобраться и дошел до следующего простого выражения, которое не работает:


import re
string = 'titleA var1 r.text(a, b, <NAME>) var11\ntitleB var2 r.text(a, b, <ip_addr1>) var22\ntitleA var3 r.text(a, b, <name>) var33\ntitleB var4 r.text(a, b, <ip_addr2>) var44'
t1 = re.findall('titleA[^(?:r\.text)]*r\.text(\([^\)]*\))',string,re.DOTALL)
print t1

Ничего не возвращает, хотя я думал вернет массив следующего вида:

'(a, b, <NAME>)'
'(a, b, <name>)'

Прошу помощи! Что я делаю не так?

Отредактировано Dezex (Дек. 8, 2015 08:47:36)

Офлайн

#2 Дек. 8, 2015 08:53:54

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

re. выбрать данные из строки, в зависимости от предыдущей

Да зачем так усложнять, читайте свой лог построчно.



Офлайн

#3 Дек. 8, 2015 08:54:28

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10016
Репутация: +  857  -
Профиль   Отправить e-mail  

re. выбрать данные из строки, в зависимости от предыдущей

>>> import re
>>> 
>>> text = """
... titleA var1 r.text(a, b, <NAME>) var11
... titleB var2 r.text(a, b, <ip_addr1>) var22
... titleA var3 r.text(a, b, <name>) var33
... titleB var4 r.text(a, b, <ip_addr2>) var44
... titleA var1 r.text(a, b, <NAME>) var11
... titleB var2 r.text(a, b, <ip_addr3>) var22
... titleA var3 r.text(a, b, <name>) var33
... titleB var4 r.text(a, b, <ip_addr4>) var44
... """
>>> 
>>> it = iter(re.findall(r'<([^>]*)>', text))
>>> out = [j for i, j in zip(it, it) if i != 'NAME']
>>> out
['ip_addr2', 'ip_addr4']
>>>



Отредактировано py.user.next (Дек. 8, 2015 12:27:55)

Офлайн

#4 Дек. 8, 2015 11:45:43

Dezex
Зарегистрирован: 2015-12-08
Сообщения: 16
Репутация: +  0  -
Профиль   Отправить e-mail  

re. выбрать данные из строки, в зависимости от предыдущей

py.user.next
Спасибо!
Правда у меня немножко посложнее строки.
Более близко вот так тогда будет:
import re
#
text = """
titleA var1 r.text(a1, b1, NAME).attr(var11)
titleB var2 r.text(a2, b2, ip_addr1).attr(var22)
<<anything, besides titleA and titleB>>
titleA var3 r.text(a3, b3, name).attr(var33)
titleB var4 r.text(a4, b4, ip_addr2).attr(var44)
 <<anything, besides titleA and titleB>>
titleA var5 r.text(a5, b5, NAME).attr(var55)
titleB var6 r.text(a6, b6, ip_addr3).attr(var66)
<<anything, besides titleA and titleB>>
titleA var7 r.text(a7, b7, name).attr(var77)
titleB var8 r.text(a8, b8, ip_addr4).attr(var88)
<<anything, besides titleA and titleB>>
"""
#
it = iter(re.findall('title[AB].*r\.text\([^\)]*\s(\w+)\)',text))
print it
#
out = [j for i, j in zip(it, it) if i != 'NAME']
out
То есть мне ориентироваться нужно по tittleA/tittleB и r.text - пояснение почему я сложно завернул в начале. + Я хотел на этапе re. выбратиь нужный текст. Но остались вопросы, помогите если не трудно):

1. Что же делает iter(x) с x - читал не понял (объект, при обращении к котороум хитрым обазом, возвращает одно значение???)
так если для моего случая:
x= ['NAME', 'ip_addr1', 'name', 'ip_addr2', 'NAME', 'ip_addr3', 'name', 'ip_addr4']

2. Что произходит при обращении к iter() через zip(): zip(y,y), где y=iter(x)

3. Почему я не могу добиться результата:
'r.text(a1, b1, NAME).attr(var11)'
если использовать код:

import re
#
text = "titleA var1 r.text(a1, b1, NAME).attr(var11)"
#
t1 = re.findall('titleA[^(?:r\.text)]*(.*)',text)
#
print t1
['r1 r.text(a1, b1, NAME).attr(var11)']
То есть я хочу, чтобы
[^(?:r\.text)]*
ело все, кроме слова r.text
(Этот вопрос возник при использовании re.DOTALL)


Отредактировано Dezex (Дек. 8, 2015 11:48:39)

Офлайн

#5 Дек. 8, 2015 12:32:35

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10016
Репутация: +  857  -
Профиль   Отправить e-mail  

re. выбрать данные из строки, в зависимости от предыдущей

Dezex
Правда у меня немножко посложнее строки.
>>> import re
>>> 
>>> text = """
... titleA var1 r.text(a1, b1, NAME).attr(var11)
... titleB var2 r.text(a2, b2, ip_addr1).attr(var22)
... <<anything, besides titleA and titleB>>
... titleA var3 r.text(a3, b3, name).attr(var33)
... titleB var4 r.text(a4, b4, ip_addr2).attr(var44)
...  <<anything, besides titleA and titleB>>
... titleA var5 r.text(a5, b5, NAME).attr(var55)
... titleB var6 r.text(a6, b6, ip_addr3).attr(var66)
... <<anything, besides titleA and titleB>>
... titleA var7 r.text(a7, b7, name).attr(var77)
... titleB var8 r.text(a8, b8, ip_addr4).attr(var88)
... <<anything, besides titleA and titleB>>
... """
>>> 
>>> it = iter(re.findall(r'^title[AB].* (.+)\)\.', text, re.M))
>>> out = [j for i, j in zip(it, it) if i != 'NAME']
>>> out
['ip_addr2', 'ip_addr4']
>>>

Dezex
Что же делает iter(x) с x - читал не понял
Контейнер превращается в итератор. Отличие в том, что в итераторе исчерпываются элементы.

Dezex
Что произходит при обращении к iter() через zip():
zip() берёт по элементу из каждого аргумента и возвращает пару. И это повторяется, пока есть элементы в обоих аргументах.
Так как аргументы - это один и тот же итератор, то при извлечении элемента в итераторе остаётся следующий элемент, поэтому пара получается из элемента и следующего за ним.

Это пример того, как действует zip()
>>> it = iter([1, 2, 3, 4])
>>> it
<list_iterator object at 0xb738deac>
>>> next(it), next(it)
(1, 2)
>>> next(it), next(it)
(3, 4)
>>> next(it), next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>



Отредактировано py.user.next (Дек. 8, 2015 12:35:58)

Офлайн

#6 Дек. 8, 2015 14:21:09

Dezex
Зарегистрирован: 2015-12-08
Сообщения: 16
Репутация: +  0  -
Профиль   Отправить e-mail  

re. выбрать данные из строки, в зависимости от предыдущей

Ага, теперь это понятно. Практически моя задача решена набор, строк на самом деле еще сложнее, но разобрался с вашей помощью.

И я так понял эта конструкция неправильная (не используется):

….. чтобы

[^(?:r\.text)]*
ело все, кроме слова r.text
(Этот вопрос возник при использовании re.DOTALL)….

Еще раз спасибо!

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version