如何使用TCL匹配此正则表达式

时间:2015-10-10 12:04:20

标签: regex list tcl

请给我一些意见。我有以下输入的TCL正则表达式。

set a {  Descriptor Blocks:
  10.132.224.74 (Tunnel42), from 10.132.224.74, Send flag is 0x0
       Composite metric is (2032896/128256), route is Internal
       Vector metric:
         Minimum bandwidth is 4096 Kbit
         Total delay is 55000 microseconds
         Reliability is 255/255
         Load is 1/255
         Minimum MTU is 1380
         Hop count is 1
         Originating router is 10.128.9.65
   10.135.0.86 (GigabitEthernet0/1), from 10.135.0.86, Send flag is 0x0
       Composite metric is (2033152/2032896), route is Internal
       Vector metric:
         Minimum bandwidth is 4096 Kbit
         Total delay is 55010 microseconds
         Reliability is 255/255
         Load is 1/255
         Minimum MTU is 1380
         Hop count is 2
         Originating router is 10.128.9.65
         Internal tag is 200 }

从上面我想要像两个列表元素一样分开,正则表达式应该跟随单词分开。

  

这里有两个接口输出,一个用于

10.132.224.74 (Tunnel42)
  

界面,另一个是

10.135.0.86 (GigabitEthernet0/1)
  

如果没有以&#34开头的行;内部标记为"在"发起路由器之后   是"它应该划分为"起源路由器是"作为一个线   列表元素。

     

如果有一行"内部标签是"之后可以使用   "始发路由器是"它应该划分为"内部标记是"   作为一个列表

我期待输出像

{Tunnel42), from 10.132.224.74, Send flag is 0x0
      Composite metric is (2032896/128256), route is Internal
      Vector metric:
        Minimum bandwidth is 4096 Kbit
        Total delay is 55000 microseconds
        Reliability is 255/255
        Load is 1/255
        Minimum MTU is 1380
        Hop count is 1
        Originating router is 10.128.9.65

10.135.0.86 (GigabitEthernet0/1), from 10.135.0.86, Send flag is 0x0
      Composite metric is (2033152/2032896), route is Internal
      Vector metric:
        Minimum bandwidth is 4096 Kbit
        Total delay is 55010 microseconds
        Reliability is 255/255
        Load is 1/255
        Minimum MTU is 1380
        Hop count is 2
        Originating router is 10.128.9.65
        Internal tag is 200

2 个答案:

答案 0 :(得分:1)

您可以使用textutil模块轻松完成此操作:

package require textutil
textutil::split::splitx $a {\n(?=\s*\d)}

这会将原始文本拆分为三个项目的列表:“描述符块:”子字符串和两个块的每个项目。它的工作原理是找到一个换行符,其中换行符和可选的空格后跟一个数字。删除换行符,但保留前导空格和数字。

Core-Tcl解决方案:

替换

regsub -all -line {^(?=\s*\d)} $a \n

将文本分成三部分(第一部分是“描述符块:”子字符串),方法是在每个块之前插入一个额外的换行符。这个解决方案显然只取决于每个块中的第一行,以一个数字开头,前面有空格。 -line选项会在换行后使^锚定。

请注意,这会产生一个包含三个部分的文本,而不是三个元素的列表:如果需要,您需要在每个双行中断处打破文本。处理此问题的另一种方法是让regsub替换插入一个不会出现在文本中的字符,然后拆分该字符,例如

split [regsub -all -line {^(?=\s*\d)} $a @] @

文档:packageregsubsplittextutil

答案 1 :(得分:1)

更通用的方法可以将输入分成行并根据需要解析它们

set a {  Descriptor Blocks:
  10.132.224.74 (Tunnel42), from 10.132.224.74, Send flag is 0x0
       Composite metric is (2032896/128256), route is Internal
       Vector metric:
         Minimum bandwidth is 4096 Kbit
         Total delay is 55000 microseconds
         Reliability is 255/255
         Load is 1/255
         Minimum MTU is 1380
         Hop count is 1
         Originating router is 10.128.9.65
   10.135.0.86 (GigabitEthernet0/1), from 10.135.0.86, Send flag is 0x0
       Composite metric is (2033152/2032896), route is Internal
       Vector metric:
         Minimum bandwidth is 4096 Kbit
         Total delay is 55010 microseconds
         Reliability is 255/255
         Load is 1/255
         Minimum MTU is 1380
         Hop count is 2
         Originating router is 10.128.9.65
         Internal tag is 200 }

set tunnelStart 0
set interfaceStart 0

set tunnelInfo {}
set interfaceInfo {}
set result {}

foreach line [split $a \n] {
    if {[regexp {\(Tunnel\d+\)} $line]} {
        # If suppose, we already identified 'tunnelInfo' and extracted it, then that variable won't be empty
        if {$tunnelInfo ne {}} {
            regsub {\n$} $tunnelInfo {} tunnelInfo
            # So, appending it to 'result'
            lappend result $tunnelInfo
            # Then, resetting the 'tunnelInfo'
            set tunnelInfo {} 
        }
        set tunnelStart 1
        set interfaceStart 0
    } elseif {[regexp {\(GigabitEthernet\d+/\d+\)} $line]} {
        # Same reason as explained above 
        if {$interfaceInfo ne {}} {
            regsub {\n$} $interfaceInfo {} interfaceInfo
            lappend result $interfaceInfo
            set interfaceInfo {} 
        }
        set interfaceStart 1
        set tunnelStart 0
    }
    if {$tunnelStart} {
        #Appending each line along with '\n'
        append tunnelInfo $line\n   
    } elseif {$interfaceStart} {
        append interfaceInfo $line\n
    }
}
#Removing the last '\n' alone 
regsub {\n$} $tunnelInfo {} tunnelInfo
regsub {\n$} $interfaceInfo {} interfaceInfo

# At last checking if the variable is not empty, append it to 'result'
if {$tunnelInfo ne {}} {
    lappend result $tunnelInfo  
} 
if {$interfaceInfo  ne {}} {
    lappend result $interfaceInfo   
}
puts $result

你可以将它们放入程序&在任何想要分开输入的地方打电话。如果假设您的输入有多个隧道和接口行信息,您可以重新编写代码以相应地解析它。