我有一个结构简单的文本文件,实际上是ftp的内容:
1.0
1.0a
10.0
10.0b
11.0
11.0f
2.0
3.0
4.0
...(and so on)
random string
random string
我正在使用get-content来获取文件的内容,但之后我希望只能检索包含最大数量和max-1数字的行。在这种情况下,例如我希望它返回:
10.0
10.0b
11.0
11.0f
我尝试使用sort-object但是没有用。有没有办法以这种方式使用排序对象,因此它知道它是排序数字而不是字符串(因此它不会在1之后放置10),然后根据完全停止之前的数字排序并忽略随机最后的字符串......
或者,如果您有其他建议方法,请这样做......谢谢。
答案 0 :(得分:2)
您可以将脚本块传递给某些cmdlet,在本例中为Sort-Object
和Group-Object
。澄清一点:
加载数据
Get-Content foo.txt |
按编号分组(忽略后缀,如果存在):
Group-Object { $_ -replace '\..*$' } |
这将首先删除字符串末尾的非数字,并使用字符串的其余部分(希望现在只包含一个浮点数)作为组名。
按数字名称排序。
Sort-Object { [int] $_.Name } |
这可以通过将组的名称转换为数字并按其排序来完成,类似于我们按照从原始行派生的内容进行分组的方式。
然后我们可以得到最后两个组,表示具有最大数量和第二个到最大数量的所有行并打开这些组。 -Last
参数是相当不言自明的,-ExpandProperty
选择属性的值而不是构造具有过滤属性列表的新对象:
Select-Object -Last 2 -ExpandProperty Group
我们有。您可以在各个阶段尝试此管道,只是为了了解命令的内容:
PS Home:\> gc foo.txt
1.0
1.0a
10.0
10.0b
11.0
11.0f
2.0
3.0
4.0
PS Home:\> gc foo.txt | group {$_ -replace '\..*$'}
Count Name Group
----- ---- -----
2 1.0 {1.0, 1.0a}
2 10.0 {10.0, 10.0b}
2 11.0 {11.0, 11.0f}
1 2.0 {2.0}
1 3.0 {3.0}
1 4.0 {4.0}
PS Home:\> gc foo.txt | group {$_ -replace '\..*$'} | sort {[int]$_.Name}
Count Name Group
----- ---- -----
2 1.0 {1.0, 1.0a}
1 2.0 {2.0}
1 3.0 {3.0}
1 4.0 {4.0}
2 10.0 {10.0, 10.0b}
2 11.0 {11.0, 11.0f}
PS Home:\> gc foo.txt | group {$_ -replace '\..*$'} | sort {[int]$_.Name} | select -l 2 -exp group
10.0
10.0b
11.0
11.0f
如果您需要按照后缀排序的组中的项目(以及最后两个组的最终结果中的项目),您可以在Sort-Object
之后直接粘贴另一个Get-Content
。
答案 1 :(得分:0)
您可以将表达式传递给Sort-Object
,然后排序将使用该表达式对对象进行排序。这是通过传递一个带有键expression
的哈希表(可以缩写为e
)来完成的。要反转订单,请添加值descending
的第二个键d
(或$true
)。
在你的情况下
...input... | Sort @{e={convert $_ as required}}
可以提供多个属性名称和哈希表:因此11.0f
可以分为数字和后缀。
如果排序表达式之间存在大量重叠,您可以先将输入预先处理为具有排序属性的对象(并在之后删除):
...input... | %{
if ($_ -match '^(\d+\.0)(.)?') {
new-object PSObject -prop @{value=$_; a=[double]::Parse($matches[1]); b=$matches[2] }
} else {
new-object PSObject -prop @{value=$_; a=[double]::MinValue; b=$null }
}
} | sort a,b | select -expand value