2

我有一个结构简单的文本文件,它实际上是一个 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 来获取文件的内容,但是我希望能够只检索包含最大数字和最大 1 数字的行。例如,在这种情况下,我希望它返回:

10.0
10.0b
11.0
11.0f

我尝试使用 sort-object 但没有用。有没有办法以这种方式使用排序对象,所以它知道它是排序数字而不是字符串(这样它不会在 1 之后放置 10),然后根据句号之前的数字排序并忽略随机最后的字符串一起...

或者,如果您有其他建议的方法,请这样做...谢谢。

4

2 回答 2

2

您可以将脚本块传递给某些 cmdlet,在这种情况下Sort-ObjectGroup-Object. 再澄清一点:

  1. 加载数据

    Get-Content foo.txt |
    
  2. 按数字分组(忽略后缀,如果存在):

        Group-Object { $_ -replace '\..*$' } |
    

    这将首先删除字符串末尾的非数字,并使用字符串的其余部分(希望现在只包含一个浮点数)作为组名。

  3. 按该组名称按数字排序。

        Sort-Object { [int] $_.Name } |
    

    只需将组的名称转换为数字并按此排序即可完成,类似于我们根据原始行派生的内容进行分组的方式。

  4. 然后我们可以得到最后两组,代表所有具有最大数量和第二大数量的行,然后展开这些组。该-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.

于 2012-04-29T10:39:03.273 回答
0

您可以将表达式传递给Sort-Object,然后排序将使用该表达式对对象进行排序。这是通过传递带有键的哈希表expression(可以缩写为e)来完成的。要反转顺序,请添加带有 value的第二个键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
于 2012-04-29T10:08:13.433 回答