2016-03-01 39 views
4

我有一個包含這樣一個文本文件:轉換字符串的一部分到變量名蟒蛇

loadbalancer { 
upstream application1 { 
server 127.0.0.1:8082; 
server 127.0.0.1:8083; 
server 127.0.0.1:8084; 
} 
upstream application2 { 
server 127.0.0.1:8092; 
server 127.0.0.1:8093; 
server 127.0.0.1:8094; 
} 
} 

有誰知道,我怎麼能提取變量象下面這樣:

appList=["application1","application2"] 
ServerOfapp1=["127.0.0.1:8082","127.0.0.1:8083","127.0.0.1:8084"] 
ServerOfapp2=["127.0.0.1:8092","127.0.0.1:8093","127.0.0.1:8094"] 



+2

後你是怎麼嘗試,到目前爲止... –

+2

我想你可能也需要一個列表字典。 'servers ['application1'] = [「127.0.0.1:8082」,「127.0.0.1:8083」,「127.0.0.1:8084」]'也可以讓你從'appList'的鍵索引哪一組服務器' –

+0

@IronFist,我試圖用正則表達式處理,但我找不到任何有效的形式 –

回答

0

這是基本的方法:

# each of your objects here 
objText = "xyz xcyz 244.233.233.2:123" 
listOfAll = re.findall(r"/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?):[0-9]{1,5}/g", objText) 

for eachMatch in listOfAll: 
    print "Here's one!" % eachMatch 

顯然,這周圍的邊緣有點粗糙,但它會進行一個全面的正則表達式搜索的任何字符串它給的。也許更好的解決方案是將對象本身傳遞給對象,但現在我不確定你會有什麼樣的原始輸入。不過,我會嘗試改進正則表達式。

3

如果線條你想始終與上游和服務器啓動這應該工作:然後

app_dic = {} 
with open('file.txt','r') as f: 
    for line in f: 
     if line.startswith('upstream'): 
      app_i = line.split()[1] 
      server_of_app_i = [] 
      for line in f: 
       if not line.startswith('server'): 
        break 
       server_of_app_i.append(line.split()[1][:-1]) 
      app_dic[app_i] = server_of_app_i 

app_dic應該是列表的字典:

{'application1': ['127.0.0.1:8082', '127.0.0.1:8083', '127.0.0.1:8084'], 
'application2': ['127.0.0.1:8092', '127.0.0.1:8093', '127.0.0.1:8094']} 

編輯

如果輸入文件不包含任何換行符,只要文件不是太大就可以將其寫入列表並迭代ove它:

app_dic = {} 
with open('file.txt','r') as f: 
    txt_iter = iter(f.read().split()) #iterator of list 
for word in txt_iter: 
    if word == 'upstream': 
     app_i = next(txt_iter) 
     server_of_app_i=[] 
     for word in txt_iter: 
      if word == 'server': 
       server_of_app_i.append(next(txt_iter)[:-1]) 
      elif word == '}': 
       break 
     app_dic[app_i] = server_of_app_i 

這是更醜陋的,因爲你必須搜索結束花括號打破。如果它變得更復雜,應使用正則表達式。

+0

你有';'包含在你的最終輸出中! –

+0

@MT你的代碼適用於每行結尾有「\ n」的配置文件,但是當我爲自己的配置文件嘗試它時,它不起作用... –

+0

@LordST如果全部打開一行,我的例子需要修改一下... –

1

如果你能夠使用newer regex module通過馬修·巴尼特,您可以採用如下方案,看到一個additional demo on regex101.com

import regex as re 

rx = re.compile(r""" 
    (?:(?P<application>application\d)\s{\n| # "application" + digit + { + newline 
    (?!\A)\G\n)        # assert that the next match starts here 
    server\s        # match "server" 
    (?P<server>[\d.:]+);     # followed by digits, . and : 
    """, re.VERBOSE) 

string = """ 
loadbalancer { 
upstream application1 { 
server 127.0.0.1:8082; 
server 127.0.0.1:8083; 
server 127.0.0.1:8084; 
} 
upstream application2 { 
server 127.0.0.1:8092; 
server 127.0.0.1:8093; 
server 127.0.0.1:8094; 
} 
} 
""" 

result = {} 
for match in rx.finditer(string): 
    if match.group('application'): 
     current = match.group('application') 
     result[current] = list() 
    if current: 
     result[current].append(match.group('server')) 

print result 
# {'application2': ['127.0.0.1:8092', '127.0.0.1:8093', '127.0.0.1:8094'], 'application1': ['127.0.0.1:8082', '127.0.0.1:8083', '127.0.0.1:8084']} 

這使得使用\G改性劑,命名捕獲組和一些編程邏輯。

0

我相信這也可以用re解決:

>>> import re 
>>> from collections import defaultdict 
>>> 
>>> APP = r'\b(?P<APP>application\d+)\b' 
>>> IP = r'server\s+(?P<IP>[\d\.:]+);' 
>>> 
>>> pat = re.compile('|'.join([APP, IP])) 
>>> 
>>> 
>>> scan = pat.scanner(s) 
>>> d = defaultdict(list) 
>>> 
>>> for m in iter(scan.search, None): 
     group = m.lastgroup 
     if group == 'APP': 
      keygroup = m.group(group) 
      continue 
     else: 
      d[keygroup].append(m.group(group)) 


>>> d 
defaultdict(<class 'list'>, {'application1': ['127.0.0.1:8082', '127.0.0.1:8083', '127.0.0.1:8084'], 'application2': ['127.0.0.1:8092', '127.0.0.1:8093', '127.0.0.1:8094']}) 

或類似的與re.finditer方法和不pat.scanner

>>> for m in re.finditer(pat, s): 
     group = m.lastgroup 
     if group == 'APP': 
      keygroup = m.group(group) 
      continue 
     else: 
      d[keygroup].append(m.group(group)) 


>>> d 
defaultdict(<class 'list'>, {'application1': ['127.0.0.1:8082', '127.0.0.1:8083', '127.0.0.1:8084'], 'application2': ['127.0.0.1:8092', '127.0.0.1:8093', '127.0.0.1:8094']})