读取来自在PowerShell中作为文本文件加载的Cisco IOS配置的行的部分

时间:2018-06-02 07:14:07

标签: powershell powershell-v4.0

我不是PowerShell的专家,但希望在powershell中编写函数来读取在PowerShell中作为文本文件加载的Cisco IOS配置中的行部分。将有多个具有不同名称的部分,每个部分都具有带有子部分的父行,如下所示。 “interface”部分有名称,“object”部分有名称,“object-group”部分有名称来过滤它们或搜索。那么如何编写函数来获取每一行的部分,然后进一步解析以从该部分获取IP。

IOS配置示例:

interface GigabitEthernet0/0
 description XXX
 speed 1000
 duplex full
 nameif XXX
 security-level 100
 ip address 1.1.1.1 255.255.255.0
!
interface GigabitEthernet0/1
 description YYY
 speed 1000
 duplex full
 nameif YYY
 security-level 100
 ip address 2.2.2.2 255.255.255.0
!
...
object network APP_NETWORK
 subnet 10.10.10.1 255.255.255.0
object network WEB_NETWORK
 host 10.10.10.2
object network DB_NETWORK
 range 10.10.10.3 10.10.10.5
...
object-group network APP_GROUP
 network-object host 10.10.20.1
 network-object host 10.10.20.2
 network-object host 10.10.20.3
object-group network WEB_GROUP
 network-object host 10.10.30.1
 network-object host 10.10.30.2
 network-object host 10.10.30.3
...

例如,我试着阅读所有“对象组网络”父节:

$config = Get-Content $runconfig -ErrorAction stop
$config | where { $_.Contains("object-group network") }

但是无法获得其子部分。如何编写函数来获取父节和子节。 例1

Get-Section(object-group network APP_GROUP)

应该返回

object-group network APP_GROUP
 network-object host 10.10.20.1
 network-object host 10.10.20.2
 network-object host 10.10.20.3

例2

Get-Section(nameif XXX) OR Get-Section(interface GigabitEthernet0/0)

应该返回类似这样的内容

interface GigabitEthernet0/0
 description XXX
 speed 1000
 duplex full
 nameif XXX
 security-level 100
 ip address 1.1.1.1 255.255.255.0
!

我搜索了很多博客,您的帮助或提示将非常感谢!谢谢!

2 个答案:

答案 0 :(得分:1)

执行此操作的一种方法是使用状态变量和适当的正则表达式。这是一个示例函数:

function Get-Section {
  param(
    [String[]] $configData,
    [String] $sectionName
  )
  $pattern = '(?:^(!)\s*$)|(?:^[\s]+(.+)$)'
  $inSection = $false
  foreach ( $line in $configData ) {
    # Skip empty lines
    if ( $line -match '^\s*$' ) {
      continue
    }
    if ( $line -eq $sectionName ) {
      $inSection = $true
      continue
    }
    if ( $inSection ) {
      if ( $line -match $pattern ) {
        [Regex]::Matches($line, $pattern) | ForEach-Object {
          if ( $_.Groups[1].Success ) {
            $_.Groups[1].Value
          }
          else {
            $_.Groups[2].Value
          }
        }
      }
      else {
        $inSection = $false
      }
      if ( -not $inSection ) {
        break
      }
    }
  }
}

如果您的示例数据位于文本文件中(例如config.txt),则可以按如下方式提取interface GigabitEthernet0/1部分:

$configData = Get-Content "config.txt"
Get-Section $configData 'interface GigabitEthernet0/1'

输出结果为:

description YYY
speed 1000
duplex full
nameif YYY
security-level 100
ip address 2.2.2.2 255.255.255.0
!

该功能不会输出该部分的名称,因为您已经知道它(您已将其传递给该功能)。

答案 1 :(得分:0)

如果您知道APP_GROUP之后的行数(在本例中为3),您可以将该值用于Select-String上的-Context开关:

$config | Select-String -Pattern '(object-group network APP_GROUP)' -Context 0,3

哪会给:

object-group network APP_GROUP
   network-object host 10.10.20.1
   network-object host 10.10.20.2
   network-object host 10.10.20.3

编辑:下面的替代正则表达式解决方案,因为没有线是动态的

$section = 'APP_GROUP'
$regex = "(?:object-group\snetwork\s$section\n)(\snetwork-object\shost\s.*\n)+(?=object-group)"

$oneline = Get-Content C:\temp\cisco.txt | Out-String
$oneline -match $regex 
$matches[0]

network-object host 10.10.20.1
network-object host 10.10.20.2
network-object host 10.10.20.3