在 powershell 中展平 netstat 命令输出

Posted

技术标签:

【中文标题】在 powershell 中展平 netstat 命令输出【英文标题】:Flatten netstat command output in powershell 【发布时间】:2019-05-07 10:43:17 【问题描述】:

我正在尝试使用 netstat -bano 并在 PowerShell 中收集输出以满足一些非常具体的报告要求。

我有工作的正则表达式,应该能够解析这个输出没有问题,但是由于输出出现在多行上,正则表达式没有被正确处理

这是 netstat 的截图

期望的输出是这样的(全部在一行上):

TCP 0.0.0.0:135 0.0.0.0:0 监听 1092 RpcSs [svchost.exe] TCP 0.0.0.0:445 0.0.0.0:0 LISTENING 4 无法获取所有权信息 TCP 0.0.0.0:623 0.0.0.0:0 监听 7404 [LMS.exe] TCP 0.0.0.0:3389 0.0.0.0:0 监听 1224 TermService [svchost.exe]

无法使用 Windows 之外的工具,所以我只限于常用工具。

在 PID 上使用Get-Process 匹配也不起作用,因为它隐藏了 svchost 和 lsass 下的子进程信息。 netstat-b 是完美的,因为它同时显示了 svchost.exe 和使用端口的进程

我已经在互联网上搜寻了一个可行的解决方案,但大多数都以不同的分辨率结束

编辑**这是我使用你们输入的最终脚本

$data = (netstat -bano |select -skip 4 | Out-String) -replace '(?m)^  (TCP|UDP)', '$1' -replace '\r?\n\s+([^\[])', "`t`$1" -replace '\r?\n\s+\[', "`t[" -split "`n"

[regex]$regex = '(?<protocol>TCP|UDP)\s+(?<address>\d+.\d+.\d+.\d+|\[::\]|\[::1\]):(?<port>\d+).+(?<state>LISTENING|\*:\*)\s+(?<pid>\d+)\s+(?<service>Can not obtain ownership information|\[\w+.exe\]|\w+\s+\[\w+.exe\])'

$output = @()

$data | foreach 
    $_ -match $regex

    $outputobj = @
        protocol = [string]$matches.protocol
        address = [string]$matches.address -replace '\[::\]','[..]' -replace '\[::1\]','[..1]'
        port = [int]$matches.port
        state = [string]$matches.state -replace "\*:\*",'NA'
        pid = [int]$matches.pid
        service = ([string]$matches.service -replace 'Can not obtain ownership information','[System' -split '.*\[')[1] -replace '\]',''
        subservice = ([string]$matches.service  -replace 'Can not obtain ownership information','' -split '\[.*\]')[0]
    
    $output += New-Object -TypeName PSobject -Property $outputobj

$output |select address,port,protocol,pid,state,service,subservice

【问题讨论】:

屏幕截图并不总是有帮助;能否将netstat 的输出重定向到一个文件,并将内容作为代码粘贴到问题中? 我有工作的正则表达式,应该能够解析这个输出没问题。它在哪里?您是否使用单行模式(?s) 之类的标志 从搜索“netstat powershell”gallery.technet.microsoft.com/scriptcenter/… 我建议使用 Kory 评论中的链接,但在这里...(netstat -bano) -join "`n" -split "(?= \w\wP\s+(?:\d+\.|\[::))"|%$_ -replace "`n",' ' -replace '\s2,',','|convertfrom-csv @KoryGill 你是对的,它没有考虑任何实际的 IPv6 地址(除了 [::])。确实如此,而且总体上效果更好:(netstat -bano | Select -skip 2) -join "`n" -split "(?= [TU][CD]P\s+(?:\d+\.|\[\w*:\w*:))"|%$_.trim() -replace "`n",' ' -replace '\s2,',','|convertfrom-csv 【参考方案1】:

我可能会这样做:

    将输出拆分为单个字符串:

    netstat -bano | Out-String
    

    删除以 UDP 或 TCP 开头的行的缩进,使它们与其他行区分开来:

    -replace '(?m)^  (TCP|UDP)', '$1'
    

    将所有不以方括号开头的缩进行连接到它们之前的行:

    -replace '\r?\n\s+([^\[])', "`t`$1"
    

    将所有以方括号开头的缩进行连接到它们之前的行:

    -replace '\r?\n\s+\[', "`t["
    

完整声明:

(netstat -bano | Out-String) -replace '(?m)^  (TCP|UDP)', '$1' -replace '\r?\n\s+([^\[])', "`t`$1" -replace '\r?\n\s+\[', "`t["

【讨论】:

谢谢!这个答案让我最接近。我唯一添加的是在换行符上拆分,以便我可以获取输出并创建一个对象【参考方案2】:

您可以加入 netstat 的输出,使其成为一个大的多行字符串,然后将其拆分为以空格开头的行,后跟 TCP 或 UDP,然后是 IP 地址(以消除应用程序的误报) “TCP 跟踪器”或其他名称)。然后从行的开头或结尾修剪任何空格,用逗号替换任何有两个或多个空格的地方,并将结果推送到ConvertFrom-Csv 以创建对象。从中您可以过滤、分组或只是通过管道发送到 Format-Table 以查看结果。

$Netstat = (netstat -bano | Select -skip 2) -join "`n" -split "(?= [TU][CD]P\s+(?:\d+\.|\[\w*:\w*:))" | 
    ForEach-Object $_.trim() -replace "`n",' ' -replace '\s2,',',' |
    ConvertFrom-Csv
# Filter the results for TCP connections and pipe the results to Format-Table
$Netstat | Where $_.Proto -eq 'TCP' | Format-Table

【讨论】:

【参考方案3】:

在 TheMadTechnician 的基础上,我发现了一些破坏他输出的案例。具体来说:netstat 有时会跳过列;当友好的应用程序名称和可执行文件都在不同的行上输出时,它会破坏 CSV 格式。这是他/她的代码的更新版本,以将这些部分考虑在内:

$netstat = (netstat -abn | Select -skip 2) -replace "Address\s2,State", "Address,State,Application" -join "`n" `
    -split "(?= [TU][CD]P\s+(?:\d+\.|\[\w*:\w*:))" | % 
        $_.trim() -replace "`n",' ' `
        -replace '\*\:\*', '*:*,' `
        -replace '\s2,', ',' `
        -replace '(.*?),(.*?),(.*?),(.*?),(.*?),', '$1,$2,$3,$4,$5 '
     | `
    ConvertFrom-Csv

【讨论】:

以上是关于在 powershell 中展平 netstat 命令输出的主要内容,如果未能解决你的问题,请参考以下文章

在powershell中展平数组

展平 Powershell 对象中的子数组,包括父对象属性

在 PowerShell 中将没有展平列表的 JSON 数组写入文件

将文件扩展名作为参数传递给powershell脚本

windows powershell的常用命令

在 IF 语句中嵌套展平;重新键入多层展平