使用正则表达式从Nagios cfg文件中提取主机名

时间:2014-07-11 13:00:24

标签: regex powershell powershell-v2.0 nagios

我有来自Nagios的配置文件,我正在成功解析以提取所有host_names。然后,我可以使用此信息与我们的服务器列表进行比较,以查看是否存在我无法监控的内容。还有其他方法可以做到这一点,但它为我的Powershell和Regex提供了借口。我的配置中的相关示例是:

define host{
    use             windows-server  ; Inherit default values from a template
    host_name       server1         ; The name we're giving to this host
    alias           server1         ; A longer name associated with the host
    address         10.10.10.19     ; IP address of the host
    }

define host{
    use             windows-server  ; Inherit default values from a template
    host_name       server2         ; The name we're giving to this host
    alias           server2         ; A longer name associated with the host
    address         10.10.13.62     ; IP address of the host
    }

define host{
    use             windows-server  ; Inherit default values from a template
    host_name       server3         ; The name we're giving to this host
    alias           server3         ; A longer name associated with the host
    address         10.10.10.21     ; IP address of the host
    }

define service{   
    use           generic-service     
    hostgroup_name        windows-servers     
    service_description   CPU Usage   
    check_command     check_nrpe!alias_cpu    
    }

define service{   
    use           generic-service     
    host_name         server1     
    service_description   Memory  
    check_command     check_nrpe!alias_mem    
    }

我有以下powershell代码段和正则表达式查询

 $text = [IO.File]::ReadAllText("windows.cfg")
 $text | Select-String '(?smi)(?<=host\{).*?(?=\})' -AllMatches |
        Foreach {$_.Matches} |
        ForEach-Object {$_.Value} |
        Select-String '(?smi)(?<=host_name\s+)\w+' -AllMatches |
        Foreach {$_.Matches} |
        ForEach-Object {$_.Value}

我匹配host {和}之间的内容,这确保我不会从服务和主机组定义中获得额外的主机。对于每个匹配,我寻找在静态主机名和一些空格之后存在的整个单词。

它确实有用,我只是想知道是否有更有效或替代的正则表达式方法。我试图让它成为一个查询,但我可以使它工作,所以我嵌套,你可以在代码中看到。我也理解

2 个答案:

答案 0 :(得分:1)

我会这样做:

$text | Select-String 'host{[\s\S]*?}' -AllMatches | % {
  $_.Matches.Groups.Value
} | Select-String 'host_name\s*(\S+)' | % {
  $_.Matches.Groups[1].Value
}

可能有一种方法可以使用单个正则表达式(不确定),但上面的内容可能更容易理解和维护。

答案 1 :(得分:0)

我通常会遇到这样的问题:

(@'
define host{
    use             windows-server  ; Inherit default values from a template
    host_name       server1         ; The name we're giving to this host
    alias           server1         ; A longer name associated with the host
    address         10.10.10.19     ; IP address of the host
    }

define host{
    use             windows-server  ; Inherit default values from a template
    host_name       server2         ; The name we're giving to this host
    alias           server2         ; A longer name associated with the host
    address         10.10.13.62     ; IP address of the host
    }

define host{
    use             windows-server  ; Inherit default values from a template
    host_name       server3         ; The name we're giving to this host
    alias           server3         ; A longer name associated with the host
    address         10.10.10.21     ; IP address of the host
    }

define service{   
    use           generic-service     
    hostgroup_name        windows-servers     
    service_description   CPU Usage   
    check_command     check_nrpe!alias_cpu    
    }

define service{   
    use           generic-service     
    host_name         server1     
    service_description   Memory  
    check_command     check_nrpe!alias_mem    
    }
'@).split("`n") |
foreach {$_.trim()} | set-content windows.cfg

get-content windows.cfg -ReadCount 1000 |
 foreach {$_ -match '^\s*host_name' -replace '^\s*host_name\s+(\S+).+','$1'}

server1
server2
server3
server1

将Get-Content与-ReadCount一起使用可让您以可控制的块处理文件数据,因此如果您在其上抛出大文件,则不会遇到内存问题。由于它将字符串数组传递给管道,因此-match和replace用作数组运算符,一次执行整个数组,-match过滤掉host_name记录,然后-replace从中提取值字符串。