【问题标题】:Searching a list in Python for a certain element and string inside element在 Python 中的列表中搜索某个元素和元素内的字符串
【发布时间】:2017-01-23 19:43:30
【问题描述】:

我已使用 readlines() 将 54,000 行日志导入 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

【问题讨论】:

  • 提供真实的工作输入以寻求帮助
  • 这个问题可能没有应有的帮助,我只是暂时无法访问我的代码文件。我希望有一个更广泛的解释,这样我就可以自学,而不是得到一个简单的答案,如果这有任何帮助的话。

标签: python string list


【解决方案1】:

您的问题有点不清楚,但这是否正确?

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

【讨论】:

  • 这绝对是我需要前进的方向。我们处理大量刀片机箱,进而处理大量刀片。最终,这将捕获存储节点和交换机信息的网络结构、BIOS、iDRAC 和类似文件。我认为这将为我提供使其工作的工具。
【解决方案2】:

一旦你有这样的一行

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的信息。

【讨论】:

  • 您说日志有空格而不是制表符是正确的。我想我最终需要利用 split(),所以确认非常好。为每个刀片保存到 self.iDRAC 是我需要做的事情,但看起来 Tagc 的建议会给我我需要的东西。
【解决方案3】:

next 呼叫您的想法是正确的。为列表创建一个迭代器,然后使用fornextitertools 中的助手来运行它。迭代器会记住它们的位置,因此如果您提前退出循环,它们只会在下一个项目处重新开始。以下是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)))

【讨论】:

    猜你喜欢
    • 2021-05-28
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-04
    相关资源
    最近更新 更多