首页 > 解决方案 > 增加文本文件中包含的版本号

问题描述

这个自我回答的问题解决了最初在文件中增加版本号中描述的场景:

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

示例文本文件内容:

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

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

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

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

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

标签: powershellversion-controlversionincrementtext-processing

解决方案


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 是默认编码;如果您需要不同的编码,请使用-Encodingwith 。 * 通过使用,该命令首先将整个文件读入内存,从而可以在同一管道中回写同一文件;但是,如果写回输入文件被中断,则存在轻微的数据丢失风险。 *总是替换与正则表达式匹配的所有子字符串。 * 内联正则表达式选项确保并匹配各个行的开头和结尾,这是必要的,因为将整个文件作为单个多行字符串读取。 Set-Content
-Raw
-replace
(?m)^$Get-Content -Raw

笔记:

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

  • 以上依赖于-replace操作员通过脚本块( { ... }) 完全动态地执行基于正则表达式的字符串替换的能力 - 如本答案中所述。

  • 正则表达式使用环视断言( (?<=...)and (?=...)) 以确保仅匹配要修改的输入部分。

    • 只有(?<=^\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 }
  • 最后/修订,如上,不管它是什么,即使后面跟着一个预发布标签(例如,; -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中,您可以使用带有and选项的语句:-replaceswitch-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

推荐阅读