Python多行正则表达式忽略字符串中的n行

时间:2017-09-13 07:45:27

标签: python regex multiline

我在编写正确的正则表达式时遇到问题。也许有人可以帮助我?

我有两个网络设备的输出:

1

Sub Demo()
    'Dim i As Long
    Dim cell As Range, cell_adr As Range 'declare cell as Range
    'Dim arr() As String
    Dim mth_exp_PM As String 'this value is taken from a different workbook and it matches one row header value

    'i = 0
    For Each cell In Range(Range("D1"), Range("D1").End(xlToRight).Offset(0, -1)).Cells
        'ReDim Preserve arr(i)
        'arr(i) = cell
        'If arr(i) = mth_exp_PM Then
        If cell = mth_exp_PM Then
            Set cell_adr = cell
            Debug.Print cell_adr.Address
        End If
        'i = i + 1
    Next cell
End Sub

2

VRF NAME1 (VRF Id = 2); default RD 9200:1; default VPNID <not set>
Old CLI format, supports IPv4 only
Flags: 0xC
Interfaces:
Gi1/1/1                 Gi1/1/4

我需要从两者中提取接口名称。

我有正则表达式:

VRF NAME2 (VRF Id = 2); default RD 101:2; default VPNID <not set>
Interfaces:
Gi0/0/3                  Gi0/0/4                  Gi0/1/4

但它只适用于第一个文本,它跳过4行,5行正是我需要的。但是,有许多路由器返回输出,如2。 问题是如何忽略未知数量的行,例如找到带有接口字的行并在&#34;接口之后提取下一行:&#34;

3 个答案:

答案 0 :(得分:1)

  

积极的背后隐藏

     

(小于?= ...)   确保给定的模式匹配,从表达式中的当前位置结束。图案必须具有固定的宽度。不消耗任何字符。

来自https://regex101.com/

正则表达式(?<=Interfaces:\n).+匹配每行后的整行&#34;接口:&#34;

我在regex101.com上测试了它,它完全适用于你的两个例子。

答案 1 :(得分:1)

编辑:在向我们提供更多输入后,答案已得到纠正。

有很多方法可以解决这个问题。看看regex101。正则表达式

(?s)VRF\s([^\s]+)\s.*?(?:RD\s([\d.]+:\d|<not\sset>));.*?Interfaces:(?:\r*\n)\s*(.*?)(?:\r*\n)

读取完整记录并捕获Interfaces后面的名称,RD值和行。

说明:

(?s)                           # single line mode: make "." read anything,
                               # including line breaks
VRF                            # every records start with VRF
\s                             # read " "
([^\s]+)                       # group 1: capture NAME VRF
\s                             # read " "
.*?                            # lazy read anything
(?:                            # start non-capture group
 RD\s                          # read "RD "
(                              # group 2
  [\d.]+:\d                    # number or ip, followed by ":" and a digit
  |                            # OR
  <not\sset>                   # value "<not set>"
)                              # group 2 end
)                              # non-caputure group end
;                              # read ";"
.*?                            # lazy read anything
Interfaces:                    # read "Interfaces:"
(?:\r*\n)                      # read newline
\s*                            # read spaces
(.*?)                          # group 3: read line after "Interfaces:"
(?:\r*\n)                      # read newline

让我们看一下测试脚本。我已经减少了脚本中记录的长度,但是消息仍然存在。

$ cat test.py
import os
import re

pattern = r"(?s)VRF\s([^\s]+)\s.*?(?:RD\s([\d.]+:\d|<not\sset>));.*?Interfaces:(?:\r*\n)\s*(.*?)(?:\r*\n)"

text = '''\
VRF BLA1 (VRF Id = 2); default RD 9200:1; default VPNID <not set>
Old CLI format, supports IPv4 only
Flags: 0xC
Interfaces:
  Gi1/1/1.451              Gi1/1/4.2019
Address family ipv4 unicast (Table ID = 0x2):
  VRF label allocation mode: per-prefix
Address family ipv6 unicast not active
Address family ipv4 multicast not active

VRF BLA2 (VRF Id = 1); default RD <not set>; default VPNID <not set>
New CLI format, supports multiple address-families
Flags: 0x1808
Interfaces:
  Gi0
Address family ipv4 unicast (Table ID = 0x1):
  Flags: 0x0
Address family ipv6 unicast (Table ID = 0x1E000001):
  Flags: 0x0
Address family ipv4 multicast not active\
'''

for rec in text.split( os.linesep + os.linesep):
    m = re.match(pattern, rec)
    if m:
        print("%s\tRD: %s\tInterfaces: %s" % (m.group(1), m.group(2), m.group(3)))

导致:

$ python test.py
BLA1    RD: 9200:1  Interfaces: Gi1/1/1.451              Gi1/1/4.2019
BLA2    RD: <not set>   Interfaces: Gi0

答案 2 :(得分:0)

有多个选项,但最接近初始尝试的选项使用可选的非捕获线:

rx = re.compile("""
VRF\s(.+?)\s\(.*RD\s(.*);.*[\n\r]
(?:^.*$[\n\r])?
(?:^.*$[\n\r])?
Interfaces:[\n\r]
(.*)""",re.MULTILINE|re.VERBOSE)

然而,第一行对我来说也很奇怪,并且没有编译(缺少右括号),但(?:^.*$[\n\r])?在您的应用程序中有效。