Powershell v2,从文件中获取特定行,排序

时间:2012-04-29 09:06:01

标签: sorting powershell

我有一个结构简单的文本文件,实际上是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),然后根据完全停止之前的数字排序并忽略随机最后的字符串......

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

2 个答案:

答案 0 :(得分: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
    
  5. 我们有。您可以在各个阶段尝试此管道,只是为了了解命令的内容:

    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