Dav*_*ago 0 powershell scripting replace windows-scripting
我需要过滤变量的内容,以将所有具有匹配字符串的行从SubnetExceptions.txt文件中排除,作为过滤器,就像一条grep -v命令一样。
$Value为了获得所需的格式,该变量经过了很多处理。
该代码的工作部分如下:
$Value=netsh dhcp server show mibinfo | findstr "Subnet Addresses"
$Value=$Value -replace "Subnet","% `n Subnet"
$Value=$Value -replace "No. of Addresses in use","AddressesInUse"
$Value=$Value -replace "No. of free Addresses","AddressesFree"
$Value=$Value -replace '^.|.$', ' '
$Value=$Value -replace ' ', ""
$Value=$Value -replace ' ', " "
$Value= -join $Value
$Value=$Value -replace '\n', ''
$Value=$Value -replace "% ", "`n"
$Value=$Value -replace ' = ', '='
Run Code Online (Sandbox Code Playgroud)
ps1的前11行$Value从以下命令处理该命令的输出():
子网= 10.1.8.0。
正在使用的地址数= 11。
免费地址数= 18。
子网= 10.1.9.0。
正在使用的地址数= 1。
免费地址数= 201。
子网= 10.1.11.0。
正在使用的地址数= 188。
免费地址数= 61。
子网= 10.1.12.0。
正在使用的地址数= 207。
免费地址数= 44。
子网= 10.1.13.0。
正在使用的地址数= 149。
免费地址数= 100。
对此:
子网= 10.1.8.0 AddressesInUse = 11 AddressesFree = 18 子网= 10.1.9.0 AddressesInUse = 1 AddressesFree = 201 子网= 10.1.11.0 AddressesInUse = 188 AddressesFree = 61 子网= 10.1.12.0 AddressesInUse = 207 AddressesFree = 44 子网= 10.1.13.0 AddressesInUse = 149 AddressesFree = 100
这些替换行适用于换行符,点,空格和“变量=值”格式。我需要将子网值放在同一行中,以便可以将其过滤掉,从而进行字符串处理。
该命令的实际输出为278行长,并有更多相同的内容,因此我将其修整为5行,以使其最小,以便在实验室中进行复制。
筛选器文件(C:\ Scripts \ SubnetExceptions.txt)的内容如下:
10.1.12.0 10.1.13.0
这些是我要过滤掉的最后两个子网值。到目前为止,已经测试过(将其添加到上面的处理之后):
$Filter = (Get-Content '.\SubnetExceptions.txt' |
ForEach-Object {[regex]::Escape($_)}) -join '|'
($Value) -notmatch $Filter | Set-Content '.\output.txt'
Run Code Online (Sandbox Code Playgroud)
预期结果应为:
子网= 10.1.8.0 AddressesInUse = 11 AddressesFree = 18 子网= 10.1.9.0 AddressesInUse = 1 AddressesFree = 201 子网= 10.1.11.0 AddressesInUse = 188 AddressesFree = 61
由于过滤器,最后两行将被删除,但输出文件仅写入值“ false”。
从第二个文件的内容构建一个正则表达式:
$re = (Get-Content '.\filter.txt' | ForEach-Object {[regex]::Escape($_)}) -join '|'
Run Code Online (Sandbox Code Playgroud)
然后使用该过滤器从您的第一个文件中排除匹配的行:
(Get-Content '.\MyList.txt') -notmatch $re | Set-Content '.\output.txt'
Run Code Online (Sandbox Code Playgroud)
如果您需要将输出同时写入文件和STDOUT,请使用Tee-Object代替Set-Content。
编辑:
现在我们可以看到更广阔的前景,我们也许可以提供一些更全面的建议。一方面,我建议将您对netsh输出的处理更改为以下形式:
$Value = netsh dhcp server show mibinfo | findstr "Subnet Addresses" | Out-String
$Value = $Value -replace '(?ms)\.\r?\n\s+No\. of ', "`t"
$Value = $Value -replace 'Addresses in use', 'AddressesInUse'
$Value = $Value -replace 'free Addresses', 'AddressesFree'
$Value = $Value -replace ' '
$Value = $Value -split '\r?\n'
$Value = $Value -replace '\.$'
Run Code Online (Sandbox Code Playgroud)
这将为您提供一个由制表符分隔的行的列表,这些行可能比您现在拥有的单个字符串更易于处理。
请注意,您也可以在单个语句中以菊花链方式链接上面列出的操作:
$Value = (netsh dhcp server show mibinfo | findstr "Subnet Addresses" | Out-String) `
-replace '(?ms)\.\r?\n\s+No\. of ', "`t" `
-replace 'Addresses in use', 'AddressesInUse' `
...
Run Code Online (Sandbox Code Playgroud)
但是,尽管分配了多项任务,我仍会坚持使用您选择的表单,因为它提供了更好的可维护性。您只需注释/取消注释行即可轻松禁用或启用单个操作。
使用行列表形式的数据,正则表达式过滤器现在将按预期工作:
$Value -notmatch $Filter | Tee-Object -FilePath '.\output.txt'
Run Code Online (Sandbox Code Playgroud)
之所以以前不起作用,是因为您只有一个字符串而不是一个字符串数组。
综上所述,我强烈建议您重新设计解决方案。尽管PowerShell完全能够解析和处理字符串,但是您忽略了许多功能,这些功能可能会使您的生活变得更加轻松。
一方面,有DHCP cmdlet将以对象形式为您提供数据,而无需解析的字符串输出netsh。但是,即使由于某种原因不能使用它们,您仍然可以将字符串输出转换为对象,例如:
...
$Value = $Value -split '\r?\n'
$Value = $Value -replace '\.$'
$obj = $Value | ForEach-Object {
$ht = $_ -replace '\t', "`n" | ConvertFrom-StringData
New-Object -Type PSObject -Property $ht
}
Run Code Online (Sandbox Code Playgroud)
或像这样:
$Value = netsh dhcp server show mibinfo | findstr "Subnet Addresses" | Out-String
$Value = $Value -replace '(?ms)\.\r?\n\s+No\. of ', "`t"
$Value = $Value -replace ' '
$obj = $Value -split '\r?\n' | Where-Object {
$_ -match '=(\d+\.\d+\.\d+\.\d+)\t.*?=(\d+)\t.*?=(\d+)'
} | ForEach-Object {
New-Object -Type PSObject -Property @{
'Subnet' = $matches[1]
'Used' = [int]$matches[2]
'Free' = [int]$matches[3]
}
}
Run Code Online (Sandbox Code Playgroud)
使用像这样的对象列表形式的数据,您可以将过滤简化为如下所示,因为您现在可以比较各个属性,而不必匹配部分字符串:
$Filter = Get-Content '.\SubnetExceptions.txt'
$obj | Where-Object {
$Filter -notcontains $_.Subnet
} | Export-Csv '.\output.csv' -NoType
Run Code Online (Sandbox Code Playgroud)
您还可以采用结构化格式(如CSV)导出数据,如果需要进一步处理数据,则可以简化传输/导入。