2017-01-23 181 views
0

我已經使用readlines()將一個54,000行的日誌導入Python。我需要從日誌中獲取可變數量的行以捕獲服務器make和固件版本。例如,這裏是從原木3行:在Python中搜索某個元素和字符串內的元素的列表

# racadm getversion 
<Server> <iDRAC Version>  <Blade Type>  <Gen> <Updatable> 
server-1 1.57.57 (Build 04)  PowerEdge M620 iDRAC7  Y 
server-2 1.57.57 (Build 04)  PowerEdge M620 iDRAC7  Y 

racadm getversion只發生在日誌中1次。可以有從1臺服務器到32臺服務器的列表。我需要解析此日誌以捕獲iDRAC版本和服務器版本,然後將它們保存到我的刀片類的類屬性(self.iDRACself.model)。還有其他的東西我需要捕捉,但我應該能夠應用這個相同的概念。

我怎麼能添加一行說(以下是不是我的實際代碼,只是一個粗略的例子):

if line in cmc.log == "# racadm getversion": 
    cmclist.next() 
    while line == "server-" 
     #do stuff to capture firmware 
+0

給予的幫助 – Harvey

+0

的問題可能不會像它應該是樂於助人實際工作的投入,我只是沒有在這個時間點訪問我的代碼文件。我希望有一個更廣泛的解釋,以便我可以教自己,而不是得到一個單一的答案,如果這有幫助的話。 – Dylan

回答

0

你的問題有點不清楚,但是這是沿着正確的線路哪兒了嗎?

簡而言之,我不知道是否用製表符或四個連續空格分隔字段,因此我使用正則表達式(\s{4}|\t)來處理這兩種情況。如果你需要,你可以改變它。

import re 

DATA = \ 
"""<Server> <iDRAC Version>  <Blade Type>  <Gen> <Updatable> 
server-1 1.57.57 (Build 04)  PowerEdge M620 iDRAC7  Y 
server-2 1.57.57 (Build 04)  PowerEdge M620 iDRAC7  Y""" 


class Blade(object): 
    def __init__(self, model, idrac): 
     self.model = model 
     self.idrac = idrac 

    def __repr__(self): 
     return 'Blade (model={}, idrac={})'.format(self.model, self.idrac) 


def parse_data(data): 
    for line in data.splitlines()[1:]: 
     model, idrac = re.split(r'(\s{4}|\t)', line)[:2] 
     yield Blade(model, idrac) 


if __name__ == '__main__': 
    for blade in parse_data(DATA): 
     print(blade) 

輸出

Blade (model=server-1, idrac=1.57.57 (Build 04)) 
Blade (model=server-2, idrac=1.57.57 (Build 04)) 
+0

這絕對是我需要向前邁進的方向。我們處理很多刀片機箱,並擴展了很多刀片。最終,這將捕獲網絡結構,BIOS,iDRAC以及用於存儲節點和交換機信息的類似文件。我認爲這會給我提供工具的工具。 – Dylan

0

一旦有了這樣

server-1 1.57.57 (Build 04)  PowerEdge M620 iDRAC7  Y 

一個線可以使用split()到單獨的每個部分出到一個數組。默認情況下,split()將以任何空格分隔字符串。但它看起來像你的字符串有一些字段中有空格。你可以通過一個標籤分割它(如果是這樣的字符串是如何分離)是這樣的:

for line in cmclist: 
    separated=line.split("\t") 
    version=separated[1] 

這裏line.split("\t")應該給你:

["server-1", "1.57.57 (Build 04)", "PowerEdge M620", "iDRAC7", "Y"] 

你可以查看更多關於split()here

+0

您說日誌中有空格而不是標籤是正確的。我想我最終需要利用split(),所以確認非常好。爲每個刀片保存self.iDRAC是我需要發生的事情,但它看起來像Tagc的建議會給我我需要的東西。 – Dylan

0

您對next致電有正確的想法。爲列表創建一個迭代器,然後使用for,nextitertools中的幫助器遍歷它。迭代器會記住它們的位置,所以如果你提前退出循環,它們只會在下一個項目重新啓動。這裏有幾個例子itertools。第二個使用yield from這是一個python 3的東西。

import itertools 

cmclog = """other stuff 
other stuff 
# racadm getversion 
<Server> <iDRAC Version>  <Blade Type>  <Gen> <Updatable> 
server-1 1.57.57 (Build 04)  PowerEdge M620 iDRAC7  Y 
server-2 1.57.57 (Build 04)  PowerEdge M620 iDRAC7  Y 
other stuff 
other stuff""".split("\n") 

def scan_server_list(cmclog): 
    server_list = [] 
    icmc = iter(cmclog) 
    try: 
     # drop everything through the racadm sentinal 
     next(itertools.dropwhile(
      lambda line: not line.startswith("# racadm getversion"), 
      icmc)) 
     # skip header 
     next(icmc) 
     # take all servers 
     server_list.extend(itertools.takewhile(
      lambda line: line.startswith("server-"), 
      icmc)) 
    except StopIteration: 
     pass 
    return server_list 

print(scan_server_list(cmclog)) 

def scan_server_list_2(cmclog): 
    icmc = iter(cmclog) 
    # drop everything through the racadm sentinal 
    next(itertools.dropwhile(
     lambda line: not line.startswith("# racadm getversion"), 
     icmc)) 
    # skip header 
    next(icmc) 
    # take all servers 
    yield from itertools.takewhile(
     lambda line: line.startswith("server-"), 
     icmc) 

print(list(scan_server_list_2(cmclog)))