【问题标题】:How do I sort a string by its numerical value in PowerShell如何在PowerShell中按其数值对字符串进行排序
【发布时间】:2018-04-25 22:18:06
【问题描述】:

我正在尝试创建一个脚本,该脚本将列出我需要列出的服务器以及从每个服务器返回的延迟,我需要根据 ping 将列表按升序或降序排列。

到目前为止,我想出的基本上已经给出了我想要的,但是如果在一台服务器上返回的 ping 高于 100,则如果其他值以高于 1 的值开始,则认为其他值更高。

我知道我需要以整数形式返回的 ping 值,但我无法弄清楚如何在不删除服务器名称的情况下准确地完成此操作。

不管怎样,这就是我到目前为止的想法

function TestNetwork {
    $global:array = @("<ServerName>:<ipaddress>"; "<ServerName>:<ipaddress>"; "<ServerName>:<ipaddress>")

    foreach ($str in $global:array) {
        $avg = 0
        $server = $($str -split ":")[0]
        $PingServer = Test-Connection -Count 3 $server
        $avg = ($PingServer | Measure-Object ResponseTime -Average)
        $calc = [System.Math]::Round($avg.Average)
        $output = "{000} | " -f $($calc) + $server
        $Output
    }
}
TestNetwork | Sort numerical -Descending `

这是我得到的结果

75 |服务器 73 |服务器 110 |服务器

【问题讨论】:

  • 您应该使用 CustomObject 输出结果,而不是将数字格式化为字符串。
  • 使用不同的字符串格式运算符右对齐数字$output = "{0,3} | " -f $($calc) + $server
  • 或者在排序的时候让RegEx do the padding left on the flyTestNetwork | Sort-Object -desending { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20) }) }

标签: powershell sorting


【解决方案1】:

有几种方法可以解决您的问题。

您可以format 将整数排序顺序和字符串排序顺序对齐为LotPings suggested 的数字:

'{0,3} | {1}' -f $calc, $server

您还可以从字符串中提取数字,将其转换回整数,并将其用作排序属性:

... | Sort-Object {[int]($_ -replace '(\d+).*', '$1')} -Descending

但是,我不建议使用任何一种方法。 PoSh 的处理方式是将对象作为Olaf pointed out 处理,因此将数据包装在自定义对象中并仅在您有理由这样做(例如创建文本输出)时将它们转换为字符串:

foreach ($str in $global:array) {
    ...
    New-Object -Type PSObject -Property ([ordered]@{
        'ComputerName' = $server
        'ResponseTime' = $calc
    })
}

这样您就可以“自然地”对数据进行排序:

TestNetwork | Sort ResponseTime -Descending | ForEach-Object {
    '{0,3} | {1}' -f $_.ResponseTime, $_.ComputerName
}

TestNetwork | Sort ResponseTime -Descending | Export-Csv 'output.csv' -NoType

【讨论】:

  • 太棒了,感谢您的回复,这非常有效!我没有使用自定义对象的原因是因为我需要输出是单行,我可以通过开关抓取和转换。再次感谢,这是一个巨大的帮助!
【解决方案2】:

以下是您做事方式的另一种选择,可以更轻松地对输出进行排序和格式化:

function Test-Network
{
    $array = ("<ServerName>","<ipaddress>"), ("<ServerName>","<ipaddress>"), ("<ServerName>","<ipaddress>")

    $array | ForEach-Object {                            
        [PsCustomObject]@{
            AvgResponse = [Math]::Round((Test-Connection -Count 3 $_[0] | Measure-Object ResponseTime -Average).Average)
            Server = $_[0]
        }
    }
}

Test-Network | 
    Sort-Object AvgResponse -Descending

输出将如下所示:

AvgResponse Server  
----------- ------  
        363 server1
         12 server2
          2 server3

输出这样的自定义对象而不是字符串的好处是,您可以在输出上使用更多的 PowerShell 技术,例如排序、分组等。

注意其他几点:

  • 除非您打算在函数外使用数组,否则无需将其声明为“全局”
  • 除非您确实需要"&lt;ServerName&gt;:&lt;ipaddress&gt;" 格式的名称,否则请考虑以不同方式存储它们。我使用了一个数组数组,这使得在这种情况下使用起来更容易,因为您不必每次都拆分一个字符串。
  • 您应该根据 PowerShell 动词-名词命名标准来命名您的函数,例如 Test-Network,而不是 TestNetwork

【讨论】:

    【解决方案3】:

    将字符串转换为整数

    TestNetwork | Sort {[int]($_.numerical)} -Descending
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-28
      • 2018-08-11
      • 1970-01-01
      • 1970-01-01
      • 2016-10-08
      • 1970-01-01
      • 2015-11-27
      • 2011-03-10
      相关资源
      最近更新 更多