Найти - Пользователи
Полная версия: re. выбрать данные из строки, в зависимости от предыдущей
Начало » Python для новичков » re. выбрать данные из строки, в зависимости от предыдущей
1
Dezex
Всем привет!
Не первый раз работаю с регулярными выражениями (правдо на автоите дело было).
Есть строки определенного вида:
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>)'

Прошу помощи! Что я делаю не так?
FishHook
Да зачем так усложнять, читайте свой лог построчно.
py.user.next
>>> 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']
>>>
Dezex
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)


py.user.next
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
>>>
Dezex
Ага, теперь это понятно. Практически моя задача решена набор, строк на самом деле еще сложнее, но разобрался с вашей помощью.

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

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

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

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