在 powershell 中展平 netstat 命令输出

Flatten netstat command output in powershell

我正在尝试使用 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 之外的工具,因此我仅限于常用工具。

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

的进程

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

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

$data = (netstat -bano |select -skip 4 | Out-String) -replace '(?m)^  (TCP|UDP)', '' -replace '\r?\n\s+([^\[])', "`t`" -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 的输出,使其成为一个大的多行字符串,然后将其拆分为以空格开头,后跟 TCP 或 UDP,再后跟 IP 地址的行(以消除误报名称为 'TCP tracker' 之类的应用程序)。然后 trim 行首或行尾的任何空格,将有两个或更多空格的任何地方替换为逗号,并将结果推送到 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 '\s{2,}',','} |
    ConvertFrom-Csv
# Filter the results for TCP connections and pipe the results to Format-Table
$Netstat | Where {$_.Proto -eq 'TCP'} | Format-Table

我可能会这样做:

  1. 将输出分解为单个字符串:

    netstat -bano | Out-String
    
  2. 删除以 UDP 或 TCP 开头的行的缩进,使它们与其他行区分开来:

    -replace '(?m)^  (TCP|UDP)', ''
    
  3. 将所有不以方括号开头的缩进行连接到它们之前的行:

    -replace '\r?\n\s+([^\[])', "`t`"
    
  4. 将所有以方括号开头的缩进行连接到它们之前的行:

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

完整语句:

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

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

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