【问题标题】:Increment a version number contained in a text file增加文本文件中包含的版本号
【发布时间】:2020-06-24 08:20:03
【问题描述】:

这个自我回答的问题解决了 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) 或 [semver] (System.Management.Automation.SemanticVersion) 实例的版本字符串,范围从 2 到 4 个组件;例如:

  • 1.0
  • 1.0.2
  • 1.0.2.3 - [version] 格式(最多 4 个数字分量)
  • 1.0.2-preview2 - [semver] 格式(最多 3 个数字分量),可选带有 - 分隔的预览标签
  • 1.0.2-preview2+001 - 同上,另外带有 +-separated 构建标签

【问题讨论】:

    标签: powershell version-control version increment text-processing


    【解决方案1】:

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

    注意:

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

    • 以上内容依赖于-replace operator 通过脚本块 ({ ... }) 完全动态执行基于正则表达式的字符串替换的能力 - 如this answer 中所述.

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

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

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

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

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

      • '2.0.9' -replace '(?&lt;=^\d+\.)\d+(?=.*)', { 1 + [int] $_.Value }
    • patch / build 编号(第三个组件;2.0.9 -> 2.0.10):

      • '2.0.9' -replace '(?&lt;=^\d+\.\d+\.)\d+(?=.*)', { 1 + [int] $_.Value }
    • last / revision 编号,如上,不管它是什么,即使后面跟着一个预发布标签(例如,; 2.0.9.10 -> 2.0.9.11 或 7.0.0-preview2 -> 7.0.1-preview2):

      • '2.0.9.10' -replace '(?&lt;=\.)\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
    

    【讨论】:

      猜你喜欢
      • 2018-09-25
      • 1970-01-01
      • 1970-01-01
      • 2016-10-18
      • 2018-03-12
      • 2010-11-02
      • 2011-04-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多