我不是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
!
我搜索了很多博客,您的帮助或提示将非常感谢!谢谢!
答案 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