Я выполняю командлет PS 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
Я хочу захватить 003
из самого высокого volume number
ABC-vol003
Я также хочу игнорировать значения, которые не имеют целочисленного значения после vol
в нем, например {{X4} } и хотят рассматривать только те значения, которые имеют целочисленное значение после vol
Я использую следующий командлет, но он генерирует неправильный вывод ABC-volDAV
Get-CustomCmdlet | Where-Object Name -match vol | select Name | Sort {$_.Name -replace '.*?(\d+)$','$1'} -descending | Select -First 1
Мой вывод должен быть ABC-vol003
4 ответа
Вы имеете в виду это?
$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 нет стандартного командлета или метода для этого.
Это передаст данные примера, отфильтрует что-либо без vol в имени, затем проверит каждое из них, чтобы убедиться, что оно содержит только цифры в последних трех символах. Он делает это путем создания переменной из трех последних символов ($ matchString) с помощью метода .SubString, а затем пытается сопоставить ее со строкой регулярных выражений вуду, $ filterMatchOnlyNumbers.
Он будет передавать только объекты, которые соответствуют фильтру. Затем он сохраняет все это в $ результатов.
# 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
Я сохранил часть выбора только самого высокого результата для последнего, используя простую трубу для сортировки, затем выбрал.
«Sort Name -Descending» сортирует его по имени и сортирует по убыванию, так что наибольшее значение будет первым.
«Select 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
Похожие вопросы
Новые вопросы
windows
Написание программного обеспечения, специфичного для операционной системы Microsoft Windows: API, поведение и т. Д. Примечание. ОБЩАЯ ПОДДЕРЖКА WINDOWS ОТКЛЮЧЕНА. Вопросы поддержки можно задать на https://superuser.com