2015-02-26 4 views
2

У меня есть файл, который содержит конфигурации. Мне нужно найти шаблон для соответствия нескольким строкам в файле конфигурации.Соответствие Множественные строки python regex

В принципе, я ищу для следующих типов линии:

class-map match-any virtualserver1 
    description virtualserver1.aaa.com 
    2 match virtual-address 172.16.211.153 tcp eq https 
    3 match virtual-address 172.16.211.153 tcp eq https 
class-map match-any virtual-server2 
    2 match virtual-address 172.16.211.154 tcp eq http 
class-map match-any vip-helloworld 
    description vs-yyy.com 
class-map match-any vip-myvirtualServer 

В файле блок как:

class-map match-any virtualserver1 
    description virtualserver1.aaa.com 
    2 match virtual-address 172.16.211.153 tcp eq https 
    3 match virtual-address 172.16.211.153 tcp eq https 

Позже, мне нужно получить имя виртуального сервера: virtualserver1 (virtualserver1.aaa.com), если присутствует и несколько виртуальных адресов и порт (172.16.211.153 и https), если они есть.

Я пробовал различные комбинации, пытаясь сопоставить блоки, но не был успешным.

import re 
fh = open('config_file.txt') 
fileData = fh.read() 
vipData = re.findall('^class-map match-.*\n.+', fileData,re.MULTILINE) 
finalList = sorted(set(vipData)) 
i = 1 
for data in finalList: 
    print str(i) +" "+ str(data) 
    i = i + 1 

Это дает мне только первую строку и вторую строку в качестве выхода для всех присутствующих конфигураций.

Какой шаблон следует использовать для соответствия всем блокам?

+0

Вы не можете сделать это на одном дыхании с регулярным выражением, потому что это не язык программирования, и понятия не имеет петель и поэтому нет возможности захватить ту же последовательность более чем один раз. Вместо этого вам нужно написать свой цикл в Python и захватить один блок за раз. Кроме того, поскольку вы хотите захватить неопределенное количество IP-адресов, вам понадобится второе регулярное выражение для извлечения тех, что находятся в цикле Python. – Bobulous

+0

@Arkanon Возможность захвата всех блоков с одним проходом. –

ответ

0
re.findall(r'(?<=class-map match-any).*?(?=class-map match-any|$)', my_str, re.DOTALL) 

Regex documentation:

(?=...) Пропускать ... матчей следующего, но не потребляет любой строки. Это называется ожидаемым утверждением.

(?<=...) соответствует, если текущему положению в строке предшествует совпадение для ..., которое заканчивается в текущей позиции. Это называется положительным утверждением lookbehind.

$ Используется так, чтобы последний матч был захвачен.

0

Ну в случае, если ваши блоки не могут иметь не более 2 «match'es, вы можете попробовать использовать это регулярное выражение:

class\-map\s+match\-any\s+(?P<servername>[\w-]+)(?:\s*description\s*(?P<description>[\w\.-]+))?(?:\s*\d+\s+match\s*virtual-address\s*(?P<IP>\d+\.\d+\.\d+\.\d+)\s+[^\r\n]*(?P<HTTP1>https?))?(?:\s*\d+\s+match\s*virtual-address\s*(?P<IP2>\d+\.\d+\.\d+\.\d+)\s+[^\r\n]*(?P<HTTP2>https?))? 

Эти названные группы будет содержать соответствующие данные:

servername 
description 
IP 
HTTP1 
HTTP2 

См. demo here.

import re 
p = re.compile(ur'class\-map\s+match\-any\s+(?P<servername>[\w-]+)(?:\s*description\s*(?P<description>[\w\.-]+))?(?:\s*\d+\s+match\s*virtual-address\s*(?P<IP>\d+\.\d+\.\d+\.\d+)\s+[^\r\n]*(?P<HTTP1>https?))?(?:\s*\d+\s+match\s*virtual-address\s*(?P<IP2>\d+\.\d+\.\d+\.\d+)\s+[^\r\n]*(?P<HTTP2>https?))?', re.MULTILINE | re.DOTALL) 
str = u"YOUR_STRING" 

re.findall(p, str) 
Смежные вопросы