仅过滤掉 PS 输出中的特定值
Filtering out only specific values in PS output
我是 运行 PS cmdlet get-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 number
中捕获 003
ABC-vol003
我也想忽略 vol
之后没有整数值的值,例如作为 ABC-volDAV
并且只想考虑其中 vol
之后具有整数值的值
我正在使用以下 cmdlet,但它生成了错误的输出 ABC-volDAV
Get-CustomCmdlet | Where-Object Name -match vol | select Name | Sort {$_.Name -replace '.*?(\d+)$',''} -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 的所有内容,然后测试每一个以确保它的最后三个字符中只有数字。它通过使用 .SubString 方法创建最后三个字符的变量($matchString)来实现这一点,然后尝试将其与正则表达式巫术字符串 $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
我只保存了 select 的部分 "highest" 最后使用简单的管道进行排序的结果,然后 select.
"Sort Name -Descending" 按名称排序,并按降序排列,使最高值排在第一位。
"Select Name"只会return管道中的"Name"部分对象,而"Select -First 1"只会return传递进来的第一件事管道。
我知道所有这些答案都有点千篇一律,但我想提供一个更强大的答案,并为之后出现的任何新手留出空间。
跟进@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(.+).*",''}}
) |
Where-Object VolumeID -match "\d{3}" |
Sort-Object VolumeID |
Select-Object -Last 1
如果您不喜欢在 Select-Object
期间创建的额外 属性,您可能希望从正则表达式过滤器中创建一个函数以便于重复使用:
function GetVolumeID {
process { $_.Name -replace ".*-vol(.+).*",'' }
}
$inputData |
Where-Object { ($_ | GetVolumeID) -match "\d{3}"} |
Sort-Object { $_ | GetVolumeID } |
Select-Object -Last 1
我是 运行 PS cmdlet get-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 number
中捕获 003
ABC-vol003
我也想忽略 vol
之后没有整数值的值,例如作为 ABC-volDAV
并且只想考虑其中 vol
之后具有整数值的值
我正在使用以下 cmdlet,但它生成了错误的输出 ABC-volDAV
Get-CustomCmdlet | Where-Object Name -match vol | select Name | Sort {$_.Name -replace '.*?(\d+)$',''} -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 的所有内容,然后测试每一个以确保它的最后三个字符中只有数字。它通过使用 .SubString 方法创建最后三个字符的变量($matchString)来实现这一点,然后尝试将其与正则表达式巫术字符串 $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
我只保存了 select 的部分 "highest" 最后使用简单的管道进行排序的结果,然后 select.
"Sort Name -Descending" 按名称排序,并按降序排列,使最高值排在第一位。
"Select Name"只会return管道中的"Name"部分对象,而"Select -First 1"只会return传递进来的第一件事管道。
我知道所有这些答案都有点千篇一律,但我想提供一个更强大的答案,并为之后出现的任何新手留出空间。
跟进@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(.+).*",''}}
) |
Where-Object VolumeID -match "\d{3}" |
Sort-Object VolumeID |
Select-Object -Last 1
如果您不喜欢在 Select-Object
期间创建的额外 属性,您可能希望从正则表达式过滤器中创建一个函数以便于重复使用:
function GetVolumeID {
process { $_.Name -replace ".*-vol(.+).*",'' }
}
$inputData |
Where-Object { ($_ | GetVolumeID) -match "\d{3}"} |
Sort-Object { $_ | GetVolumeID } |
Select-Object -Last 1