在Python中搜索elemen中的某个元素和字符串

2024-04-26 12:31:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经使用readlines()将54000行日志导入到Python中。我需要从日志中提取不同数量的行来捕获服务器的版本和固件的修订。例如,日志中有3行:

# 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

Tags: 代码buildself版本服务器数量serverline
3条回答

您对next调用的想法是正确的。为列表创建一个迭代器,然后使用fornextitertools中的助手来遍历它。迭代器会记住它们的位置,因此如果您提前退出循环,它们只会在下一项时重新启动。这里有几个itertools的例子。第二个使用yield from,这是python3。你知道吗

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)))

一旦你有了这样一条线

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。你知道吗

你的问题有点不清楚,但这是正确的吗?你知道吗

简单地说,我不知道是用制表符还是四个连续的空格来分隔字段,所以我用正则表达式(\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))

相关问题 更多 >