【问题标题】:Parsing Netsh output解析 Netsh 输出
【发布时间】:2021-02-23 14:19:36
【问题描述】:

我需要在 powershell 中解析 netsh 命令给出的输出。 以下是我正在使用的命令

Netsh advfirewall show private

证明下面的输出

Private Profile Settings: 
----------------------------------------------------------------------
State                                 ON
Firewall Policy                       BlockInbound,AllowOutbound
LocalFirewallRules                    N/A (GPO-store only)
LocalConSecRules                      N/A (GPO-store only)
InboundUserNotification               Enable
RemoteManagement                      Disable
UnicastResponseToMulticast            Enable

Logging:
LogAllowedConnections                 Disable
LogDroppedConnections                 Disable
FileName                              %systemroot%\system32\LogFiles\Firewall\pfirewall.log
MaxFileSize                           4096

我的要求是访问上述输出中的每个值。类似 $result.state / $result.InboundUserNotification

我对 PowerShell 还是很陌生,我在 google 上搜索过这方面的内容,但没有找到任何东西。

【问题讨论】:

  • 您是否尝试过使用“Get-NetFirewallProfile Private”?这在所有当前的 Windows 版本中都可以做到。
  • 我试过这个。但是 Get-NetFirewallProfile 存在问题。你可以参考这个linkNetsh 正在给我本地计算机上的当前设置
  • 我不知道这个特定的 cmdlet,但总的来说 netsh 被认为已弃用,如果发生冲突,应该首选 powershell cmdlet。

标签: windows powershell parsing


【解决方案1】:

如果您必须解析此输出,您可以执行以下操作:

$netsh = (Netsh advfirewall show private |
    Select-String -Pattern "\s{2,}") -replace '\s{2,}','=' -replace '\\','\\' -join [System.Environment]::NewLine
$result = [pscustomobject](ConvertFrom-StringData $netsh)

ConvertFrom-StringData 方法的问题是哈希表输出没有排序。如果顺序很重要,您可以通过将每一行拆分为属性/值对来创建哈希表:

$hash = [ordered]@{}
Netsh advfirewall show private | Select-String -Pattern "\s{2,}" |
    Foreach-Object {
         $key,$value = $_ -split '\s{2,}'
         $hash[$key] = $value
    }
$result = [pscustomobject]$hash

【讨论】:

  • 这很漂亮。
【解决方案2】:

这是使用ConvertFrom-StringData 以及Foreach-Object-Begin-End 参数的AdminOfThings answer 的类似方法。

Netsh advfirewall show private |
     ForEach-Object -Begin{$ht = [ordered]@{}} {
        if($_ -match '\s{10,}')
        {
            $ht += $_ -replace '\\','\\' -replace '\s{10,}','=' | ConvertFrom-StringData
        }
    } -End{[PSCustomObject]$ht} -OutVariable result

还有一点变化

Netsh advfirewall show private | Where-Object {$_ -match '\s{10,}'} |
     ForEach-Object -Begin{$ht = [ordered]@{}} {
        $ht += $_ -replace '\\','\\' -replace '\s{10,}','=' | ConvertFrom-StringData
    } -End{[PSCustomObject]$ht} -OutVariable result

【讨论】:

    【解决方案3】:

    强制性推荐:

    文本解析总是不如基于对象的解决方案健壮,尽管 PowerShell 提供了许多强大的功能(如果需要),特别是在这种情况下带有 -Regex 选项的 switch 语句:

    $result = [ordered] @{}  # initialize the (ordered) result hashtable.
    
    # Process each line output by netsh, and if it is a line 
    # containing a property/value-pair, add an entry to the hashtable.
    switch -Regex (netsh advfirewall show private)  {
      '^(.+?) {2,}(.+)' { $result[$Matches.1] = $Matches.2 }
    }
    
    # Now you can access $result.State, $result.'Firewall Policy', ...
    

    请注意假设属性名称及其值至少由两个空格分隔
    ( {2,});与属性/值模式不匹配的行将被跳过。


    一个替代方法是假设一个固定列宽,用一个空格分隔列,这似乎是这里的情况:

    $result = [ordered] @{}  # initialize the (ordered) result hashtable.
    
    # Process each line output by netsh, and if it is a line 
    # containing a property/value-pair, add an entry to the hashtable.
    switch -Regex (netsh advfirewall show private)  {
      '^(.{37}) (.+)' { $result[($Matches.1).TrimEnd()] = $Matches.2 }
    }
    

    注意$Matches.1 周围的(...)(括号),这是在值上调用.TrimEnd() 时意外需要的;如果使用 index syntax ([1]) 而不是 property syntax .1,则不需要括号(也就是说,$Matches[1].TrimEnd() 可以使用)。该问题似乎特定于 数字 的属性/键名称。见GitHub issue #14036

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      • 2020-12-17
      • 2019-01-22
      • 2014-10-19
      • 2013-02-03
      • 2020-06-10
      相关资源
      最近更新 更多