Regex слишком "жадный", как это исправить
необходимо из вывода подобно этому:
VID Type Ports
--------------------------------------------------------------------------------
1 common UT:GE0/0/15(D) GE0/0/16(D) GE0/0/18(D) GE0/0/19(D)
GE0/0/21(D) XGE0/0/1(D) XGE0/0/2(D) XGE0/0/3(D)
XGE0/0/4(D)
TG:GE0/0/24(U)
3 common UT:GE0/0/14(U) GE0/0/22(U) GE0/0/24(U)
TG:XGE0/0/1(D) XGE0/0/2(D)
6 common UT:GE0/0/17(U) GE0/0/20(U)
TG:GE0/0/24(U) XGE0/0/1(D) XGE0/0/2(D)
12 common TG:GE0/0/24(U) XGE0/0/1(D) XGE0/0/2(D)
105 common TG:GE0/0/24(U) XGE0/0/1(D) XGE0/0/2(D)
107 common TG:GE0/0/24(U) XGE0/0/1(D) XGE0/0/2(D)
888 common UT:GE0/0/1(D) GE0/0/2(D) GE0/0/3(D) GE0/0/4(D)
GE0/0/5(D) GE0/0/6(D) GE0/0/7(D) GE0/0/8(D)
GE0/0/9(D) GE0/0/10(D) GE0/0/11(D) GE0/0/12(D)
GE0/0/13(D)
TG:GE0/0/24(U) XGE0/0/1(D) XGE0/0/2(D)
VID Status Property MAC-LRN Statistics Description
получить имена всех untagged интерфейсов 888 VLAN (все что между UT:и TG:) если я пишу:
r'^888\s+common\s+UT:(.+)(?=\([U|D]\)\s*).+TG:'
возвращаются все интерфейсы от первого до последнего если
r'^888\s+common\s+UT:(.*?)(?=\([U|D]\)\s*).+TG:'
то только первый GE0/0/1. как написать выражение чтобы вернуло все GE..... без (D)
Ответы (2 шт):
Если у вас нет явного шаблона, то не следует все решать одним регекспом
import re
data = '''
VID Type Ports
--------------------------------------------------------------------------------
1 common UT:GE0/0/15(D) GE0/0/16(D) GE0/0/18(D) GE0/0/19(D)
GE0/0/21(D) XGE0/0/1(D) XGE0/0/2(D) XGE0/0/3(D)
XGE0/0/4(D)
TG:GE0/0/24(U)
3 common UT:GE0/0/14(U) GE0/0/22(U) GE0/0/24(U)
TG:XGE0/0/1(D) XGE0/0/2(D)
6 common UT:GE0/0/17(U) GE0/0/20(U)
TG:GE0/0/24(U) XGE0/0/1(D) XGE0/0/2(D)
12 common TG:GE0/0/24(U) XGE0/0/1(D) XGE0/0/2(D)
105 common TG:GE0/0/24(U) XGE0/0/1(D) XGE0/0/2(D)
107 common TG:GE0/0/24(U) XGE0/0/1(D) XGE0/0/2(D)
888 common UT:GE0/0/1(D) GE0/0/2(D) GE0/0/3(D) GE0/0/4(D)
GE0/0/5(D) GE0/0/6(D) GE0/0/7(D) GE0/0/8(D)
GE0/0/9(D) GE0/0/10(D) GE0/0/11(D) GE0/0/12(D)
GE0/0/13(D)
TG:GE0/0/24(U) XGE0/0/1(D) XGE0/0/2(D)
VID Status Property MAC-LRN Statistics Description
'''
finds = " ".join(data.split("\n")[3:-3])
finds = re.findall(r"UT:(.*?)TG:", finds)
res = []
[res.extend(x.split()) for x in finds]
print(res)
['GE0/0/15(D)', 'GE0/0/16(D)', 'GE0/0/18(D)', 'GE0/0/19(D)', 'GE0/0/21(D)',
'XGE0/0/1(D)', 'XGE0/0/2(D)', 'XGE0/0/3(D)', 'XGE0/0/4(D)', 'GE0/0/14(U)',
'GE0/0/22(U)', 'GE0/0/24(U)', 'GE0/0/17(U)', 'GE0/0/20(U)', 'GE0/0/1(D)',
'GE0/0/2(D)', 'GE0/0/3(D)', 'GE0/0/4(D)', 'GE0/0/5(D)', 'GE0/0/6(D)',
'GE0/0/7(D)', 'GE0/0/8(D)', 'GE0/0/9(D)', 'GE0/0/10(D)', 'GE0/0/11(D)',
'GE0/0/12(D)', 'GE0/0/13(D)']
я знал что сюда просится textFSM, но не представлял как написать шаблон. задал гуглу правильный вопрос и получил пример. решается все гораздо проще huawei_int_by_vlan.template:
Value List INTF (\w+\d\/\d\/\d+)
Start
^\s+TG: -> Continue.Record
^888\s+common\s+UT:${INTF}\( -> Continue
^888\s+common\s+UT:\S+\s+${INTF}\( -> Continue
^888\s+common\s+UT:\S+\s+\S+\s+${INTF}\( -> Continue
^888\s+common\s+UT:\S+\s+\S+\s+\S+\s+${INTF}\( -> Continue
^\s+${INTF}\( -> Continue
^\s+\S+\s+${INTF}\( -> Continue
^\s+\S+\s+\S+\s+${INTF}\( -> Continue
^\s+\S+\s+\S+\s+\S+\s+${INTF}\( -> Continue
и тогда
def proba():
data = '''
dis vlan | beg 888
The total number of VLANs is: 7
--------------------------------------------------------------------------------
U: Up; D: Down; TG: Tagged; UT: Untagged;
MP: Vlan-mapping; ST: Vlan-stacking;
#: ProtocolTransparent-vlan; *: Management-vlan;
--------------------------------------------------------------------------------
VID Type Ports
--------------------------------------------------------------------------------
888 common UT:GE0/0/1(D) GE0/0/2(D) GE0/0/3(D) GE0/0/4(D)
GE0/0/5(D) GE0/0/6(D) GE0/0/7(D) GE0/0/8(D)
GE0/0/9(D) GE0/0/10(D) GE0/0/11(D) GE0/0/12(D)
GE0/0/13(D)
TG:GE0/0/24(U) XGE0/0/1(D) XGE0/0/2(D)
VID Status Property MAC-LRN Statistics Description
--------------------------------------------------------------------------------
1 enable default enable disable VLAN 0001
3 enable default enable disable VLAN 0003
6 enable default enable disable VLAN 0006
12 enable default enable disable VLAN 0012
105 enable default enable disable VLAN 0105
107 enable default enable disable VLAN 0107
888 enable default enable disable VLAN 0888
'''
tf = myini.templpath + 'huawei_int_by_vlan.template'
with open(tf) as tmpl:
fsm = textfsm.TextFSM(tmpl)
result = fsm.ParseText(data)
print(result)
возвращает:
[[['GE0/0/2', 'GE0/0/5', 'GE0/0/6', 'GE0/0/7', 'GE0/0/8', 'GE0/0/9', 'GE0/0/10', 'GE0/0/11', 'GE0/0/12', 'GE0/0/13']], [['XGE0/0/1', 'XGE0/0/2']]]
мне с шаблоном удобно, в зависимости от бренда (циско, хуавей) просто буду давать разные команды и разные шаблоны использовать а код унифицируется