【问题标题】:Parse RegEx IP matches in Powershell array在 Powershell 数组中解析 RegEx IP 匹配项
【发布时间】:2018-05-15 20:26:18
【问题描述】:

我正在尝试研究如何解析 IP 地址的数组。到目前为止,我已经弄清楚了如何将 IP 解析为 DNS 主机名:

Function Get-IP-Hostname
{
    Param([string[]]$array)

    $array.length

    foreach ($element in $array) 
    {
        $hname = [System.Net.Dns]::GetHostByAddress($element).HostName 

        $regex = "[regex] (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"

        @{$element = $hname}
     }
 } 

当我执行时

Get-IP-Hostname 192.168.150.xx 192.168.151.xx  

对于一堆 IP,我必须使用逗号来拆分、分隔字符串 - 我的 RegEx 似乎没有逗号就无法拆分。

我正在尝试得到这个输出:

> Name                           Value                                  
> 
> ----                           -----                                                                                                                                                                                                                               
> 192.168.150.xx                 ank70dom07.akgroup.com                                                                                                                                                                                                             
> 192.168.151.xx                 ank70dom07.akgroup.com

我是 PowerShell 的新手,希望能提供任何帮助。

谢谢!

【问题讨论】:

    标签: arrays regex powershell split match


    【解决方案1】:

    如果您希望能够以这种方式(作为额外参数)传递参数,请在参数上使用 [ValueFromRemainingArguments()]

    还有一种比正则表达式更好的方法来验证 IP 地址:只需将其转换为 [ipaddress]

    function Get-IP-Hostname {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromRemainingArguments = $true)]
        [String[]]
        $IPAddress
    )
    
        foreach ($element in $IPAddress) {
            $ip = $element -as [Net.IPAddress]
            if ($ip) {
                @{$element = [Net.Dns]::GetHostByAddress($element).HostName}
            } else {
                # handle invalid IP (or don't)
            }
        }
    }
    

    您可以通过将参数设置为 IP 地址数组 ([ipaddress[]]) 来进一步简化此操作,因为字符串的转换将自动完成:

    function Get-IP-Hostname {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromRemainingArguments = $true)]
        [IPAddress[]]
        $IPAddress
    )
    
        foreach ($ip in $IPAddress) {
            @{$ip = [Net.Dns]::GetHostByAddress($ip.IPAddressToString).HostName}
        }
    }
    

    这里的问题是,即使传入的地址之一无效,整个调用也会失败。所以这取决于你想做什么。

    还有一个建议:不要每次都返回带有单个元素的新哈希表。它在屏幕上看起来很正确,但这不是您真正想要的。您可以使用单个哈希表来修复它,但我建议使用更好的方法:返回一个带有 HostName 属性的 [IPAddress] 对象:

    function Get-IP-Hostname {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromRemainingArguments = $true)]
        [String[]]
        $IPAddress
    )
    
        foreach ($element in $IPAddress) {
            $ip = $element -as [Net.IPAddress]
            if ($ip) {
                $ip |
                    Add-Member -NotePropertyName HostName -NotePropertyValue ([Net.Dns]::GetHostByAddress($ip.IPAddressToString).HostName) -PassThru
            } else {
                # handle invalid IP (or don't)
            }
        }
    }
    
    $results = Get-IP-Hostname 8.8.4.4 8.8.8.8
    
    $results | fl * # all properties
    
    $results | ft IPAddressToString,HostName # demonstrating what you want
    

    【讨论】:

    • 不知道那个属性,太好了!
    【解决方案2】:

    摆脱您的$Array 参数并使用自动变量$Args。它已经是接收到的所有参数的数组。

    PS C:\> Function Get-HostnameFromIP { $Args }
    PS C:\> Get-HostnameFromIP 134.222.659.0 148.398.388.299
    134.222.659.0
    148.398.388.299
    

    这种方法的唯一障碍是您需要将参数转换为您希望它们成为的(字符串)[Net.Dns]::GetHostByAddress("$Element")

    编辑:测试了这种方法,IPv4 地址在 PSv5.1 中已被解释为[String]

    【讨论】:

      【解决方案3】:

      您可以使用-match 参数。例如

      PS C:\> "192.168.0.1" -match "(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"  
      True
      

      如果找到匹配,则返回 True。您可以从$Matches 变量中检索匹配结果:

      PS C:\> $Matches
      
      Name                           Value                                                                                                                      
      ----                           -----                                                                                                                      
      1                              192.168.0.1                                                                                                                
      0                              192.168.0.1                                                                                                                
      

      $Matches 是一个数组(包含正则表达式匹配组),因此您可以通过 []-operator 检索特定值

      PS C:\> $Matches[1]
      192.168.0.1  
      

      您还可以通过管道传输多个字符串并检查其中一个是否与正则表达式匹配:

      PS C:\>"192.168.0.23", "10.0.0.1" | % { if ($_ -match "(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})") { $Matches[0]} }
      

      您还应该查看此llink,更详细地解释-matches

      希望对您有所帮助。

      【讨论】:

      • 我希望能够将正则表达式保留在 get-IP-Hostname 函数中,所以我可以粘贴一堆 IP,它会捡起并将其放入错误中,而不需要逗号。例如。 PS C:\> 192.168.0.23 djfhsd 10.0.0.1
      【解决方案4】:

      使用函数“ResolveIPs”并使用 RegEx 公式仅提取 IP,对 RegEx 使用“.matches”,然后使用“TRY”解析主机名。最后将结果输出到数组中。

      function ResolveIPs {
          cls #clear console
          $regex = [regex] "\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}"
          $table = @() 
      
          foreach ($argument in $args){ 
              if ($argument -match $regex){ 
                  $tempstr = $regex.Matches($argument) | %{ $_.value } 
      
                  foreach ($value in $tempstr){
                      $tablevalue = "" | select IP, Hostname 
                      try {
                          $result = [Net.Dns]::GetHostByAddress($value).HostName
      
                          $tablevalue.IP = $value 
                          $tablevalue.Hostname = $result 
                          $table = $table + $tablevalue 
                      }
                      catch [exception] { 
                          $tablevalue.IP = $value 
                          $tablevalue.Hostname = "Error resolving IP address" 
                          $table = $table + $tablevalue
                      }
                  }  #endof foreach value
              }#end of IF
          }#endof foreach argument
      
          $table #output of table with results
      }#end of function
      

      您现在可以将此脚本作为模块 (.psm1) 导入,并在函数“ReolveIPs”之后添加任何 IP。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-01
        • 2017-09-22
        • 1970-01-01
        • 2010-11-08
        • 2020-04-15
        • 1970-01-01
        相关资源
        最近更新 更多