我正在尝试在powerhell管道中对组中的对象进行排名。
Get-ChildItem "*.csv" |
Select-object fullname, Length, @{N = "Environment"; E = {
if ($_.fullname -like "*Dev*") {
"DEV"
}
elseif ($_.fullname -like "*PROD*") {
"PROD"
}
elseif ($_.fullname -like "*UAT*") {
"UAT"
}
}} | Sort-Object -Property Environment, Length
我想在组(环境和长度)的基础上在管道中添加具有以下值的Rank
属性。在SQL ranking function
FullName Length Environment Rank
-------- ------ ----------- ----
C:\Temp\ReportDEV-20171210_210653.csv 3065 DEV 1
C:\Temp\ReportDEV-20171210_211041.csv 9116 DEV 2
C:\Temp\ReportDEV-20171210_190100.csv 76286 DEV 3
C:\Temp\ReportDEV-20171210_200229.csv 511546 DEV 4
C:\Temp\ReportPROD-20171210_210349.csv 2835 PROD 1
C:\Temp\ReportPROD-20171210_210754.csv 8897 PROD 2
C:\Temp\ReportPROD-20171210_184729.csv 43850 PROD 3
C:\Temp\ReportPROD-20171210_191133.csv 213202 PROD 4
C:\Temp\ReportUAT-20171210_210554.csv 3065 UAT 1
C:\Temp\ReportUAT-20171210_210920.csv 9116 UAT 2
C:\Temp\ReportUAT-20171210_185308.csv 57244 UAT 3
C:\Temp\ReportUAT-20171210_193211.csv 306154 UAT 4
答案 0 :(得分:1)
您可以使用for循环将排名简单地添加到输出对象。
ForEach-Object
在第一个参数中接受脚本块作为开始脚本。我用它来声明计数器然后是第二个参数,它是用于处理脚本的,除了创建所需的输出对象之外,我还增加了计数器。
示例1 - 行的行号:
Get-ChildItem "C:\SomeDirectory" -Recurse -File | Sort-Object Name |
ForEach-Object {$i = 1} {
New-Object psObject -Property @{Name= $_.Name; Rank= $i++;}
}
结果
Name Rank
---- ----
Product1-1.txt 1
Product1-2.txt 2
Product1-3.txt 3
Product2-1.txt 4
Product2-2.txt 5
示例2 - 组中行的行号:
Get-ChildItem "C:\SomeDirectory" -Recurse -File | Group-Object DirectoryName |
ForEach-Object {
$_.Group | ForEach-Object {$i = 1} {
New-Object psObject -Property @{
GroupName= $_.Directory.Name; Name= $_.Name;Rank= $i++;
}
}
}
结果
GroupName Name Rank
--------- ---- ----
Category1 Product1-1.txt 1
Category1 Product1-2.txt 2
Category1 Product1-3.txt 3
Category2 Product2-1.txt 1
Category2 Product2-2.txt 2
答案 1 :(得分:1)
不幸的是,PowerShell 不提供开箱即用的排名功能,因此需要额外的工作:
$rank = 0
$prevEnv = ''
Get-ChildItem *.csv | Select-Object FullName, Length, @{
n='Environment'; e={ $_.Name -replace '.*(DEV|PROD|UAT).*', '$1' } } |
Sort-Object Environment, Length | Select-Object *, @{
n='Rank'; e={
++$rank
if ($prevEnv -ne $_.Environment) {
$rank = 1
Set-Variable -Scope 1 prevEnv $_.Environment
}
Set-Variable -Scope 1 rank $rank
$rank
}
}
注意将输入文件名映射到.Environment
属性中的环境名称的简化方法,使用带有正则表达式的-replace
和捕获组从文件名中提取感兴趣的令牌
通过.Environment
添加Select-Object
属性后,对象首先按.Environment
排序,然后按.Length
排序(文件大小,以字节为单位)。
然后通过另一个.Rank
调用为结果对象提供Select-Object
属性,其值为基于1
的序列号,每当新的{{1遇到值,实际上相当于每个环境的文件大小排名。
请注意.Environment
需要修改Set-Variable
和$rank
变量,因为这些变量必须在整个管道范围内按顺序维护为了使它们能够在连续的$prevEnv
调用中持续存在(相反,例如,在分配给键Select-Object
的脚本块中,本地e
变量将仅限于该脚本块)。
或者,使用$rank
(更简洁,但效率更低):
Group-Object
Get-ChildItem *.csv | Select-Object FullName, Length, @{
n='Environment'; e={ $_.Name -replace '.*(DEV|PROD|UAT).*', '$1' }
} |
Group-Object Environment | ForEach-Object {
$rank = 0
$_.Group | Sort-Object Length | Select-Object *, @{
n='Rank'; e={ Set-Variable -Scope 1 rank ($rank+1); $rank }
}
}
按新添加的Group-Object Environment
属性对输入对象进行分组。
.Environment
遍历所有结果组。
ForEach-Object
)成员都是通过$_
属性枚举的,并按.Group
排序。第二个.Length
调用然后循环遍历长度排序的组成员,并生成具有Select-Object
属性的扩充输出对象,该属性反映基于文件的基于1的组相对排名尺寸(长度)按升序排列。
请注意.Rank
需要增加Set-Variable
变量,因为该变量必须保持在$rank
主体的级别,以便在连续的数据中存在ForEach-Object
调用(在分配给键Select-Object
的脚本块内部,本地e
变量仅限于该脚本块)。