【问题标题】:Parsing text in python issue在 python 问题中解析文本
【发布时间】:2012-04-03 21:19:14
【问题描述】:

我正在尝试找出如何从该文本文件中获取每个 AP 行上的客户端数量,这对于具有“客户端数量”关联的那些似乎很好(在下一个行),但您可以查看是否没有客户端与之关联,它不会打印客户端数量。

我无法弄清楚检查下一行以查看是否存在“客户端数量”的逻辑,然后返回当前行。如果它存在,它应该继续到下一行并获取客户编号。如果没有“客户端数量”行,我正在尝试将客户端设置为 0。

我有一个包含以下内容的文件:

无线细节.txt

RUDY>show wireless ap detail on AP1 | include clients
RUDY>show wireless ap detail on AP2 | include clients
 Num of clients       : 8  
RUDY>show wireless ap detail on AP3 | include clients
 Num of clients       : 21
RUDY>show wireless ap detail on AP4 | include clients
RUDY>show wireless ap detail on AP5 | include clients
 Num of clients       : 2

现在我有以下内容:

for line in file:   
    if "AP" in line:
        ap = re.search('AP[0-99]+', line)
        print ap.group(0),
    elif "Num of clients" in line:  
        clients = re.search('[0-99]+', line)
        print '- ' + clients.group(0)

它当前打印以下内容:

AP1 AP2 - 8
AP3 - 21
AP4 AP5 - 2
AP6 - 5
AP7 - 2
AP8 - 5
AP9 - 5

让它检查下一行以查看 AP 是否应设置为 0 个客户端的最佳方法是什么?

编辑:FWIW - 我正在尝试 file.next() 读取下一行,这似乎有效,但我无法回到上一行:/

编辑#2:我希望我能投票给你们所有人。谢谢大家!难以置信有这么多方法可以做到,我想不出其中一种!!!!

【问题讨论】:

  • 我建议您使用它可能具有的编程接口之一来查询您的无线控制器平台,例如SNMP、XML-RPC/SOAP。然后你可以绘制关联计数。
  • 嗨,马特,我最初尝试通过 SNMP 进行,但关联计数的查询是通过控制器列出的,并且我没有分配给 AP 的 IP。 :(

标签: python file parsing text


【解决方案1】:

这里有一个使用正则表达式的简短方法。注意 re.MULTILINE 标志

s='''RUDY>show wireless ap detail on AP1 | include clients
RUDY>show wireless ap detail on AP2 | include clients
 Num of clients       : 8  
RUDY>show wireless ap detail on AP3 | include clients
 Num of clients       : 21
RUDY>show wireless ap detail on AP4 | include clients
RUDY>show wireless ap detail on AP5 | include clients
 Num of clients       : 2'''
import re
print re.findall(r'(AP\d) \| include clients(?:$\n Num of clients {7}: (\d))?',s,flags=re.M)

(?:$\n Num of clients {7}: (\d))? 构成一个非捕获组,并且使用 ?最后,它是可选的。如果它没有捕获,第二个匹配组将为空,就像 1 和 4 一样。

" {7}" 表示 7 个空格

打印这个:

  [('AP1', ''), ('AP2', '8'), ('AP3', '2'), ('AP4', ''), ('AP5', '2')]

【讨论】:

    【解决方案2】:

    如果您希望数据采用更结构化的格式(例如字典),您可以试试这个:

    with open('wireless-detail.txt', 'r') as fp:
        access_points = {}
        ap = None
        for line in fp:
            if 'AP' in line:
                ap = line[line.find('AP'):line.find('|')].strip()
                access_points[ap] = 0
            elif "Num of clients" in line:
                access_points[ap] = int(line.split(':')[1].strip())
    
    print access_points
    

    返回:

    {'AP2': 8, 'AP3': 21, 'AP1': 0, 'AP4': 0, 'AP5': 2}
    

    我同意以前的解决方案,即 re 对此类任务来说是不必要的复杂化,因为您的文件是可靠输出的。这种方法的一个好处是您还可以获得关于没有连接用户的已知接入点的信息,例如,AP1 = 0(也是 int() 形式!)

    【讨论】:

      【解决方案3】:

      你想多了。不要使用正则表达式。他们很慢,有问题,而且你的模式定义得很好。做类似...

      for line in file:
          if "AP" in line:
              i = line.find('AP')
              splitLine = line[i+2:].split('|')
              val = splitLine[0]
              print val,
          elif "Num of clients" in line:
              splitLine = line.split(':')
              num = splitLine[1]
              print '- ' + num
      

      【讨论】:

      • 此解决方案会产生明显不可读的输出,使用关键字作为变量名,并且可重用性差(打印后无法使用提取的数据)。 :(
      【解决方案4】:

      如果你打算使用 RE,你可以这样做。变量用于确定是否需要计数线。如果计数线可用,则使用它,否则设置为- 0

      need_count = 0
      for line in file:   
          if "AP" in line:
              if need_count:
                 print '- 0'
              ap = re.search('AP[0-99]+', line)
              print ap.group(0)
              need_count = 1
          elif "Num of clients" in line:  
              clients = re.search('[0-99]+', line)
              print '- ' + clients.group(0)
              need_count = 0
      

      【讨论】:

        【解决方案5】:

        这可能有点矫枉过正,但是这里......

        我创建了一个库,其中包含一些经常派上用场的类似函数:

        def fileLineGroups (f, count=2, truncate=True):
            lines = []
            for line in f:
                lines.append(line)
                if len(lines) == count:
                    yield lines
                    lines = lines[1:]
            if not truncate:
                if lines:
                    yield lines
        

        这将遍历打开的文件句柄的行,产生行组。它默认为 2 组,因此它将返回 [line1, line2],然后是 [line2, line3] 等。如果您将 truncate 保留为打开状态,如果其中没有 count 行,它将不会返回最终组.这使您可以执行for a, b in fileLineGroups(f) 之类的操作,而不会在最后一个计数为奇数时出错。

        现在你可以这样做了:

        import re
        def getAPClientCounts (filepath):
            with open(filename) as f:
                for line1, line2 in py.fileLineGroups(f):
                    match1 = re.search('AP\d*', line1)
                    if match1:
                        match2 = re.search('Num of clients.*: (\d*)', line2)
                        if match2:
                            yield match1.group(), match2.groups()[0]
        
        for ap, count in getAPClientCounts('wireless-detail.txt'):
            print 'AP with name %s has %s clients' % (ap, count)
        
        AP with name AP2 has 8 clients
        AP with name AP3 has 21 clients
        AP with name AP5 has 2 clients
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-07-05
          • 2019-12-03
          • 1970-01-01
          • 1970-01-01
          • 2013-08-20
          • 2015-10-29
          • 2011-09-05
          • 2011-11-02
          相关资源
          最近更新 更多