增加文本文件中包含的版本号

Increment a version number contained in a text file

这个自答问题解决了 Increment version number in file 中最初描述的场景:

文本文件中嵌入的版本号将递增。

示例文本文件内容:

nuspec{
    id = XXX;
    version: 0.0.30;
    title: XXX;

例如,我希望将嵌入式版本号 0.0.30 更新为 0.0.31

可以假定感兴趣的行与以下正则表达式匹配:^\s+version: (.+);$

请注意,目的不是用 固定 新版本替换版本号,而是 增加现有版本

理想情况下,增量逻辑将处理表示 [version] (System.Version) or [semver] (System.Management.Automation.SemanticVersion) 个实例的版本字符串,范围从 2 - 4 个组件;例如:

PowerShell [Core] (v6.1+)中,一个简洁的解决方案是可能的:

$file = 'somefile.txt'
(Get-Content -Raw $file) -replace '(?m)(?<=^\s+version: ).+(?=;$)', {
    # Increment the *last numeric* component of the version number.
    # See below for how to target other components.
    $_.Value -replace '(?<=\.)\d+(?=$|-)', { 1 + $_.Value }
  } | Set-Content $file

注:
* 在 PowerShell [Core] 6+ 中,无 BOM UTF-8 是默认编码;如果您需要不同的编码,请使用 -EncodingSet-Content
* 通过使用-Raw,该命令首先将整个文件读入内存,这样可以在同一管道中写回同一文件;但是,如果回写输入文件被中断,则存在轻微的数据丢失风险。
* -replace 总是替换 所有 与正则表达式匹配的子字符串。
* 内联正则表达式选项 (?m) 确保 ^$ 匹配 个别行 的开始和结束,这是必要的,因为 Get-Content -Raw 将整个文件作为单个多行字符串读取。

注:

  • 为简单起见,基于文本 对版本字符串进行操作,但您也可以将 $_.Value[version][semver](仅限 PowerShell [Core] v6+)并使用它。
    基于文本的操作的优点是能够简洁地按原样保留输入版本字符串的所有其他组件,而无需添加以前未指定的组件。

  • 以上依赖于's ability to perform regex-based string substitutions fully dynamically, via a script block ({ ... }) - as explained in .

  • 正则表达式使用look-around assertions(?<=...)(?=...))以确保只匹配要修改的输入部分。

    • 只有 (?<=^\s+version: )(?=;$) 环视特定于示例文件格式;根据需要调整这些部分以匹配文件格式中的版本号。

以上增量是输入版本的最后一个数字 组件。 要定位各种版本号组件,请改用以下内部正则表达式:

  • 增加主要数字(例如,2.0.9 -> 3.0.9) :

    • '2.0.9' -replace '\d+(?=\..+)', { 1 + [int] $_.Value }
  • :

    • '2.0.9' -replace '(?<=^\d+\.)\d+(?=.*)', { 1 + [int] $_.Value }
  • 补丁/构建编号(第3个组件;2.0.9 -> 2.0.10):

    • '2.0.9' -replace '(?<=^\d+\.\d+\.)\d+(?=.*)', { 1 + [int] $_.Value }
  • last / revision number,如上,随便它是,即使后面跟着预发布标签(例如,2.0.9.10 -> 2.0.9.117.0.0-preview2 -> 7.0.1-preview2):

    • '2.0.9.10' -replace '(?<=\.)\d+(?=$|-)', { 1 + [int] $_.Value }

注意:如果目标组件不存在,则原样返回原始版本。


Windows PowerShell 中,-replace 不支持基于脚本块的替换,您可以使用 switch 语句使用 -File-Regex 选项代替:

$file = 'someFile.txt'
$updatedFileContent = 
  switch -regex -file $file { # Loop over all lines in the file.

    '^\s+version: (.+);$' { # line with version number

      # Extract the old version number...
      $oldVersion = $Matches[1]

      # ... and update it, by incrementing the last component in this
      # example.
      $components = $oldVersion -split '\.'
      $components[-1] = 1 + $components[-1]

      $newVersion = $components -join '.'

      # Replace the old version with the new version in the line
      # and output the modified line.
      $_.Replace($oldVersion, $newVersion)

    }

    default { # All other lines.
      # Pass them through.
      $_ 
    }
}

# Save back to file. Use -Encoding as needed.
$updatedFileContent | Set-Content $file