字符串为多行时某些某些正则表达式无法正确匹配

时间:2018-08-16 04:38:52

标签: python regex python-2.7

我刚刚开始学习基本编程以解决实际问题。目前,我正在使用Python进行一些正则表达式方面的工作,希望在这里能得到一点帮助。

我需要远程登录到网络交换机,获取其固件版本,然后才能执行其他操作。因此,命令“ show switch”的输出如下所示: (请注意,根据主要和辅助版本上实际运行的特定固件版本,可能会或可能不会显示“ patchX-X”行。)

switch1.1 # show switch

SysName:          switch1
SysLocation:
SysContact:       support@extremenetworks.com, +1 888 257 3000
System MAC:       00:01:02:03:04:05
System Type:      X440

SysHealth check:  Enabled (Normal)
Recovery Mode:    All
System Watchdog:  Enabled

Current Time:     Mon Dec 31 00:00:00 2000
Timezone:         [Auto DST Disabled] GMT Offset: 0 minutes, name is UTC.
Boot Time:        Mon Dec 31 00:00:00 2000
Boot Count:       1
Next Reboot:      None scheduled
System UpTime:    0 minutes 0 seconds

Current State:    OPERATIONAL
Image Selected:   primary
Image Booted:     primary
Primary ver:      12.3.4.5
                  patch1-2
Secondary ver:    12.6.7.8
                  patch3-4

Config Selected:  primary.cfg
Config Booted:    primary.cfg

以下Python代码用于从上述输出中提取版本。 所需的结果将是priVer ==“ 12.3.4.5 patch1-2”和secVer ==“ 12.6.7.8 patch3-4”。

def updateReadout():
    global readout
    readout = tn.read_very_eager()

def checkFirmware():
    global priVer
    global secVer
    global priPatch
    global secPatch

    tn.write("show switch\n")

    updateReadout()

    priVer = re.findall(r"(?<=Primary ver:\s{6})\S+",readout)[0] 
    secVer = re.findall(r"(?<=Secondary ver:\s{4})\S+",readout)[0]

    try: 
        priPatch = re.findall(r"(?<=Primary ver:\s{6}\S{8}\s{19})\S+",readout)[0]
        priVer = priVer + " " + priPatch
    except IndexError: 
        print "Oops!IndexError!"
        pass

    try: 
        secPatch = re.findall(r"(?<=Secondary ver:\s{4}\S{8}\s{19})\S+",readout)[0]
        secVer = secVer + " " + secPatch
    except IndexError: 
        print "Oops!IndexError!"
        pass

    print "\n" + "Primary Version = " + priVer
    print "Secondary Version = " + secVer + "\n"

但是,奇怪的是,我可以很好地获得“ 12.3.4.5”和“ 12.6.7.8”,但是在尝试获取下一行的“补丁”信息时,经常会发生IndexError,而Regex101确认我确实得到了完美搭配: https://regex101.com/r/4ptQ05/1

运行代码可以给我以下信息:

Oops!IndexError!
Oops!IndexError!

Primary Version = 12.3.4.5
Secondary Version = 12.6.7.8

然后,奇怪的是,使用相同的Regex复制并粘贴“ show switch”命令的结果并手动传递给变量“ readout”看起来确实很好:

import re

readout = """
SysName:          switch1
SysLocation:
SysContact:       support@extremenetworks.com, +1 888 257 3000
System MAC:       00:01:02:03:04:05
System Type:      X440

SysHealth check:  Enabled (Normal)
Recovery Mode:    All
System Watchdog:  Enabled

Current Time:     Mon Dec 31 00:00:00 2000
Timezone:         [Auto DST Disabled] GMT Offset: 0 minutes, name is UTC.
Boot Time:        Mon Dec 31 00:00:00 2000
Boot Count:       1
Next Reboot:      None scheduled
System UpTime:    0 minutes 0 seconds

Current State:    OPERATIONAL
Image Selected:   primary
Image Booted:     primary
Primary ver:      12.3.4.5
                  patch1-2
Secondary ver:    12.6.7.8
                  patch3-4

Config Selected:  primary.cfg
Config Booted:    primary.cfg
"""

def regexCheck():
    global priVer
    global secVer
    global priPatch
    global secPatch
    global readout

    priVer = re.findall(r"(?<=Primary ver:\s{6})\S+",readout)[0] 
    secVer = re.findall(r"(?<=Secondary ver:\s{4})\S+",readout)[0]

    try: 
        priPatch = re.findall(r"(?<=Primary ver:\s{6}\S{8}\s{19})\S+",readout)[0]
        priVer = priVer + " " + priPatch
    except IndexError: 
        print "Oops!IndexError!"
        pass

    try: 
        secPatch = re.findall(r"(?<=Secondary ver:\s{4}\S{8}\s{19})\S+",readout)[0]
        secVer = secVer + " " + secPatch
    except IndexError: 
        print "Oops!IndexError!"
        pass

def main():
  regexCheck()
  print "Primary Version = " + priVer
  print "Secondary Version = " + secVer

main()

运行上述代码将返回:

Primary Version = 12.3.4.5 patch1-2
Secondary Version = 12.6.7.8 patch3-4

所以我想知道这里是否存在某种“多行字符串格式”问题,但是搜索或没有根据的试探没有运气。

任何想法都将不胜感激...

谢谢!

更新:

将iTerm2中的所有行直接复制/粘贴到SublimeText或网页上的此文本框可能不会保留原始格式,因此我首先readout = readout.replace("\r\n", "@\r\n"),然后print readout,现在看起来像这样:

switch1.1 # show switch@
@
SysName:          switch1@
SysLocation:      @
SysContact:       support@extremenetworks.com, +1 888 257 3000@
System MAC:       00:01:02:03:04:05@
System Type:      X440@
@
SysHealth check:  Enabled (Normal)@
Recovery Mode:    All@
System Watchdog:  Enabled@
@
Current Time:     Mon Dec 31 00:00:00 2000@
Timezone:         [Auto DST Disabled] GMT Offset: 0 minutes, name is UTC.@
Boot Time:        Mon Dec 31 00:00:00 2000@
Boot Count:       1@
Next Reboot:      None scheduled@
System UpTime:    0 minutes 0 seconds @
@
Current State:    OPERATIONAL             @
Image Selected:   primary                 @
Image Booted:     primary                 @
Primary ver:      12.3.4.5                @
                  patch1-2@
Secondary ver:    12.6.7.8    @
@
Config Selected:  primary.cfg                                          @
Config Booted:    primary.cfg                                          @
@
primary.cfg       Created by ExtremeXOS version 15.7.1.4@
                  123456 bytes saved on Mon Dec 31 00:00:00 2000@
switch1.2 #

2 个答案:

答案 0 :(得分:0)

>>> d = {}
... prev_key = None
... for line in readout.splitlines():
...     try:
...         key, value = line.split(':', maxsplit=1)
...     except ValueError:
...         current_line = line.strip()
...         if current_line:
...             d[prev_key] += ' {}'.format(current_line)
...     else:
...         d[key] = value.strip()
...         prev_key = key
... 
>>> import json; print(json.dumps(d, indent=2))
{
  "SysName": "switch1",
  "SysLocation": "",
  "SysContact": "support@extremenetworks.com, +1 888 257 3000",
  "System MAC": "00:01:02:03:04:05",
  "System Type": "X440",
  "SysHealth check": "Enabled (Normal)",
  "Recovery Mode": "All",
  "System Watchdog": "Enabled",
  "Current Time": "Mon Dec 31 00:00:00 2000",
  "Timezone": "[Auto DST Disabled] GMT Offset: 0 minutes, name is UTC.",
  "Boot Time": "Mon Dec 31 00:00:00 2000",
  "Boot Count": "1",
  "Next Reboot": "None scheduled",
  "System UpTime": "0 minutes 0 seconds",
  "Current State": "OPERATIONAL",
  "Image Selected": "primary",
  "Image Booted": "primary",
  "Primary ver": "12.3.4.5 patch1-2",
  "Secondary ver": "12.6.7.8 patch3-4",
  "Config Selected": "primary.cfg",
  "Config Booted": "primary.cfg"
}
>>> d['Primary ver']
'12.3.4.5 patch1-2'
>>> d['Secondary ver']
'12.6.7.8 patch3-4'

答案 1 :(得分:0)

我认为问题出在脚本处理换行与编辑器之间的不匹配。

我运行了您的代码,并将所有“ \ n”替换为“ \ r \ n”,并得到了与针对开关运行脚本时得到的结果相同的结果:

>>> main()
Primary Version = 12.3.4.5 patch1-2
Secondary Version = 12.6.7.8 patch3-4
>>> readout = readout.replace("\n", "\r\n")
>>> main()
Oops!IndexError!
Oops!IndexError!
Primary Version = 12.3.4.5
Secondary Version = 12.6.7.8

请仔细检查telnet会话是否未添加您不期望的任何其他回车符。或更改正则表达式以与此匹配。