Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Powershell 正确排序包含版本号的列表_Powershell_Sorting_Version Numbering - Fatal编程技术网

Powershell 正确排序包含版本号的列表

Powershell 正确排序包含版本号的列表,powershell,sorting,version-numbering,Powershell,Sorting,Version Numbering,我有一个版本列表,如下所示: v1.1.0 v1.2.0 v1.3.0 v1.4.0 v1.5.0 v1.7.0 v1.8.0 v1.9.0 v2.0.0 v2.1.0 v2.10.0 v2.11.0 v2.12.0 v2.2.0 v2.3.0 v2.4.0 v2.5.0 v2.6.0 v2.7.0 v2.8.0 v2.9.0 $location = Get-Location $path = $location.tostring() + "\CHANGELOG.md" $tags = git

我有一个版本列表,如下所示:

v1.1.0
v1.2.0
v1.3.0
v1.4.0
v1.5.0
v1.7.0
v1.8.0
v1.9.0
v2.0.0
v2.1.0
v2.10.0
v2.11.0
v2.12.0
v2.2.0
v2.3.0
v2.4.0
v2.5.0
v2.6.0
v2.7.0
v2.8.0
v2.9.0
$location = Get-Location
$path = $location.tostring() + "\CHANGELOG.md"
$tags = git tag
$i = 0

Clear-Content $path
Add-Content $path "Change Log"
Add-Content $path "=========="
Add-Content $path " "

$ToNatural = { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20) }) }
$tags | Sort-Object $ToNatural

foreach($tag in $tags) 
{
    if (-NOT ($tag -match "v(\d+\.)(\d+\.)(\*|\d+)")) { continue }
    $i = $i + 1
    if ($i -eq 0) { continue }
    $tag
    If ($i -gt 0) {
        $previous = $tags[$i - 1]

        Add-Content $path " "
    }
}
问题是,它们的订购不正确。 我是Powershell的新手,因此在尝试对其进行排序时遇到了一些问题。 我试着这样做:

$tags = git tag
$versions = $tags | %{ new-object System.Version ($_) } | sort
但我得到了这个错误:

新对象:使用“1”参数调用“.ctor”时发生异常:“版本字符串部分太短或太长。” 第1行字符:24 +$versions=$tags |%{new object System.Version($|)}排序 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +CategoryInfo:InvalidOperation:(:)[New Object],MethodInvocationException +FullyQualifiedErrorId:ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

有人能帮忙吗


更新 我使用的解决方案如下所示:

v1.1.0
v1.2.0
v1.3.0
v1.4.0
v1.5.0
v1.7.0
v1.8.0
v1.9.0
v2.0.0
v2.1.0
v2.10.0
v2.11.0
v2.12.0
v2.2.0
v2.3.0
v2.4.0
v2.5.0
v2.6.0
v2.7.0
v2.8.0
v2.9.0
$location = Get-Location
$path = $location.tostring() + "\CHANGELOG.md"
$tags = git tag
$i = 0

Clear-Content $path
Add-Content $path "Change Log"
Add-Content $path "=========="
Add-Content $path " "

$ToNatural = { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20) }) }
$tags | Sort-Object $ToNatural

foreach($tag in $tags) 
{
    if (-NOT ($tag -match "v(\d+\.)(\d+\.)(\*|\d+)")) { continue }
    $i = $i + 1
    if ($i -eq 0) { continue }
    $tag
    If ($i -gt 0) {
        $previous = $tags[$i - 1]

        Add-Content $path " "
    }
}
这类工作正常,但所有标记似乎都是控制台记录的,它显示了以下内容:

1.6.0
changeDeliveryFieldAccess
orders/autoComplete
returns/autoComplete
save-lines-dates
services/serviceDetails
tile-colours
users/confirmation
v0.1
v1.1.0
v1.2.0
v1.3.0
v1.4.0
v1.5.0
v1.7.0
v1.8.0
v1.9.0
v2.0.0
v2.1.0
v2.2.0
v2.3.0
v2.4.0
v2.5.0
v2.6.0
v2.7.0
v2.8.0
v2.9.0
v2.10.0
v2.11.0
v2.12.0
v.2.7.1
正如你所看到的,有一些是我不想要的。具体而言:

1.6.0
changeDeliveryFieldAccess
orders/autoComplete
returns/autoComplete
save-lines-dates
services/serviceDetails
tile-colours
users/confirmation
v.2.7.1
一旦这些从我的列表中清除,那么顺序将正确:)


更新2 因此,我尝试了另一种可能更好的解决方案:

$location=获取位置 $path=$location.tostring()+“\CHANGELOG.md” $tags=git标签 $i=0

Clear-Content $path
Add-Content $path "#Change Log"
Add-Content $path "=========="
Add-Content $path " "

$tags |
  Where-Object { $_.Substring(1) -as [version] } |
   Sort-Object { [version] $_.Substring(1) }

foreach($tag in $tags) {
    write-host "$($tag) is ok"
}
我不确定这是否正确,但这是上述代码的输出:

1.6.0 is ok
changeDeliveryFieldAccess is ok
orders/autoComplete is ok
returns/autoComplete is ok
save-lines-dates is ok
services/serviceDetails is ok
tile-colours is ok
users/confirmation is ok
v.2.7.1 is ok
v0.1 is ok
v1.1.0 is ok
v1.2.0 is ok
v1.3.0 is ok
v1.4.0 is ok
v1.5.0 is ok
v1.7.0 is ok
v1.8.0 is ok
v1.9.0 is ok
v2.0.0 is ok
v2.1.0 is ok
v2.10.0 is ok
v2.11.0 is ok
v2.12.0 is ok
v2.2.0 is ok
v2.3.0 is ok
v2.4.0 is ok
v2.5.0 is ok
v2.6.0 is ok
v2.7.0 is ok
v2.8.0 is ok
v2.9.0 is ok

我相信,如果您想对这些字符串进行排序而不出现问题,您需要将它们正确地解析为版本对象


$tags=@(
“v1.1.0”
“v1.2.0”
“v1.3.0”
“v1.4.0”
“v1.5.0”
“v1.7.0”
“v1.8.0”
“v1.9.0”
“v2.0.0”
“v2.1.0”
“v2.10.0”
“v2.11.0”
“v2.12.0”
“v2.2.0”
“v2.3.0”
“v2.4.0”
“v2.5.0”
“v2.6.0”
“v2.7.0”
“v2.8.0”
“v2.9.0”
)
#----------------------------------------------------------------------------# 
#解析将失败,因为字符串中的“v”不是有效的语义版本控制
#----------------------------------------------------------------------------# 
$tags |%{
$tag=$_
$version=[version]::new()
if([version]::TryParse($tag,[ref]$version))
{
$version
}
其他的
{“ParseFailed--$($tag)”}
}|排序对象
#----------------------------------------------------------------------------# 
#已成功解析字符串#
#----------------------------------------------------------------------------# 
$tags |%{
$tag=$\替换“[a-zA-Z]”
$version=[version]::new()
if([version]::TryParse($tag,[ref]$version))
{
$version
}
其他的
{“ParseFailed--$($tag)”}
}|排序对象

如果还想将返回的对象用作
2.1.0
类型的字符串,则可以在该对象上添加
ToString()

tl;博士

您后来指出,
$tags
数组还包含其他非版本字符串,因此必须过滤掉这些字符串:

  • 其中对象{$\.Substring(1)-as[version]}
    只传递那些可以转换为
    [version]
    System.version
    )对象的字符串-
    -as[version]
    -在移除开头的
    v
    后(
    .Substring(1)
    ;忽略移除
    v
    是您最初的问题);
    -as
    运算符返回成功转换的值或
    $null

  • Sort Object
    然后将过滤后的标记作为版本号进行排序,这将产生正确的顺序-有关说明,请参阅下一节

  • $sortedVersionTags
    然后只接收正确排序的原始形式的版本标记(如
    v
    前缀字符串)


版本号中的
v
前缀阻止它们转换为
[System.version]
实例;只需首先将其删除(不是从输入本身删除;只是暂时删除,以便创建版本信息对象,例如,
v1.1.0
->
1.1.0

此外,还可以简化您的命令:

# $tags is an array of lines, as output by `git tag`
$tags | Sort-Object { [version] $_.Substring(1) }
  • [version]
    是内置在PowerShell中的类型加速器(简称),它引用了
    [System.version]
    [1]

  • 您只需将字符串强制转换为
    [version]
    ,这比使用
    新对象
    更简洁、更快

  • 排序对象
    通过脚本块(
    {…}
    )接受表达式,以代替要排序的固定属性;在脚本块中,
    $\uuu
    表示给定的输入对象
    $\子字符串(1)
    只需删除第一个字符(
    v

    • 请注意,该表达式仅暂时用于排序<代码>排序对象仍然输出原始字符串-已排序
通过您的示例输入,上述结果(注意
v2.10.0
如何在
v2.9.0
之后正确排序,这与词汇排序不同):


如果希望输出
System.Version
实例
而不是输入字符串,则命令会变得更简单(PSv3+语法):

如果
$tags
中包含的所有字符串都可能无法通过这种方式转换(由于没有
v
格式),请使用以下(PSv4+语法):

此方法确保遇到无法转换的字符串时不会破坏整个命令

  • 可以转换的是,并且是输出

  • 无法转换的内容将导致打印到控制台的错误,并将在以后的自动
    $error
    集合中反映出来。您可以使用
    2>$null
    抑制控制台输出


[1] 一般来说,PowerShell是
[version[]] $tags.Substring(1) | Sort-Object
# Reports non-convertible lines as non-terminating errors, but processes all others.
$tags.ForEach({ [version] $_.Substring(1) }) | Sort-Object
$tags | Sort-Object {[Version]($_ -replace "[a-zA-Z]","")}
v1.1.0
v1.2.0
v1.3.0
v1.4.0
v1.5.0
...
$ToNatural = { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20) }) }
$tags | Sort-Object $ToNatural

v1.1.0
v1.2.0
v1.3.0
...
v2.7.0
v2.8.0
v2.9.0
v2.10.0
v2.11.0
v2.12.0