仅过滤掉 PS 输出中的特定值



我正在运行PS cmdletget-customcmdlet,它正在生成以下输出

Name                         FreeSpaceGB
----                         -----------
ABC-vol001                   1,474.201
ABC-vol002                   2,345.437     
ABC-vol003                   3,147.135
ABC-volDAV                   4,147.135
ABC-volCDA                   5,147.135

我想从最高volume numberABC-vol003捕获003我还想忽略vol后没有整数值的值,例如ABC-volDAV,只想考虑其中vol后具有整数值的值

我正在使用以下 cmdlet,但它生成了错误的输出ABC-volDAV

Get-CustomCmdlet | Where-Object Name -match vol | select Name | Sort {$_.Name -replace '.*?(d+)$','$1'} -descending |  Select -First 1

我的输出应该是ABC-vol003

你是这个意思吗?

$inputData = @"
"Name","FreeSpaceGB"
"ABC-vol001","1474.201"
"ABC-vol002","2345.437"     
"ABC-vol003","3147.135"
"ABC-volDAV","4147.135"
"@ | ConvertFrom-Csv
$inputData |
Where-Object { $_.Name -match '-vol[d]+' } |
Sort-Object { [Int] $_.FreeSpaceGB } -Descending |
Select-Object -First 1

上面输出的是:

Name       FreeSpaceGB
----       -----------
ABC-vol003 3147.135

根据评论 - 这是猜测提问者想要做什么的另一种尝试:

$inputData = @"
"Name","FreeSpaceGB"
"ABC-vol001","1474.201"
"ABC-vol002","2345.437"     
"ABC-vol003","3147.135"
"ABC-volDAV","4147.135"
"@ | ConvertFrom-Csv
$inputData |
Where-Object { $_.Name -match '-vol[d]+' } |
Select-Object `
Name,
@{Name = "Volume"; Expression = { [Regex]::Match($_.Name, 'd+$').Value }},
FreeSpaceGB |
Sort-Object Volume -Descending

此代码输出以下内容:

Name       Volume FreeSpaceGB
----       ------ -----------
ABC-vol003 003    3147.135  
ABC-vol002 002    2345.437  
ABC-vol001 001    1474.201

因此,在这里,我们在包含卷号(使用正则表达式提取(的输出对象中创建一个计算属性(自定义列(,并按该属性进行排序。

你有10卷以上的书吗?

Get-CustomCmdlet | ? Name -Notmatch ".*d{3}$" | sort Name -Descending

否则

Get-CustomCmdlet | ? Name -match ".*d{3}$" | sort {[int]($_.Name -replace "w{3}-w{3}","")} -Descending

我想添加一个更以PowerShell为中心并且具有较少正则表达式的答案。

我只在过滤器中使用正则表达式来测试字符串是否都是数字,因为据我所知,PowerShell 中没有固定的 cmdlet 或方法来执行此操作。

这将对示例数据进行管道处理,过滤掉名称中没有 vol 的任何内容,然后测试每个数据以确保它只有最后三个字符中的数字。 它$matchString通过使用 .SubString 方法,然后尝试将其与正则表达式 voodoo 字符串进行匹配,$filterMatchOnlyNumbers。

它只会传递与过滤器匹配的对象。 然后它将所有这些保存到$results中。

# example data set
$inputData = @"
"Name","FreeSpaceGB"
"ABC-vol001","1474.201"
"ABC-vol002","2345.437"     
"ABC-vol003","3147.135"
"ABC-volDAV","4147.135"
"ABC-volCDA","5147.135"
"ABC-volS4D","6147.135"
"@ | ConvertFrom-Csv
# regex voodoo to detect only numbers
$filterMatchOnlyNumbers = '^[d.]+$'
# filter to only return results that have "vol" in name
$nameFilter = '*vol*'
# do work and store to $results
$results = (
$inputData |
Where {$_.Name -like $nameFilter} |
ForEach {
# get last 3 characters of name
$matchString = $_.Name.Substring($_.Name.Length - 3)
If ($matchString -match $filterMatchOnlyNumbers){
# pass this on if it is only numbers
$_
}
}
)
# print results (only highest)
$results | Sort Name -Descending | Select Name -First 1

我保存了仅选择"最高"结果的部分,最后使用简单的管道进行排序,然后选择。

"排序名称 - 降序"按名称排序并按降序排序,以便最高值排在第一位。

"选择 Name"将仅返回管道中对象的"Name"部分,而"Select -First 1"将仅返回管道中传递的第一件事。

我知道所有这些答案都有点相同,但我想提供一个更强大的答案,并为在此之后出现的任何新手提供间隔。

跟进@Bill_Stewart的答案。保存"VolumeID"以供以后参考似乎很有价值。此代码通过 Select-Object 将其添加为计算字段,为你提供一个名称,以便稍后在管道中进行筛选和排序。

$inputData = @"
"Name","FreeSpaceGB"
"ABC-vol001","1474.201"
"ABC-vol002","2345.437"
"ABC-vol003","3147.135"
"ABC-volDAV","4147.135"
"ABC-volCDA","5147.135"
"ABC-volS4D","6147.135"
"@ | ConvertFrom-Csv

$inputdata | Select-Object -Property @(
'Name'
'FreeSpaceGB'
@{l='VolumeID';e={$_.name -replace ".*-vol(.+).*",'$1'}}
) |
Where-Object VolumeID -match "d{3}" | 
Sort-Object VolumeID | 
Select-Object -Last 1

如果您不喜欢在Select-Object期间创建的额外属性,您可能希望从正则表达式过滤器中创建一个函数以便于重用:

function GetVolumeID {
process { $_.Name -replace ".*-vol(.+).*",'$1' }
}
$inputData |
Where-Object { ($_ | GetVolumeID) -match "d{3}"} |
Sort-Object { $_ | GetVolumeID } |
Select-Object -Last 1

最新更新