问题
This self-answered question addresses the scenario originally described in Increment version number in file:
A version number embedded in a text file is to be incremented.
Sample text-file content:
nuspec{
id = XXX;
version: 0.0.30;
title: XXX;
For instance, I want embedded version number 0.0.30 updated to 0.0.31.
The line of interest can be assumed to match the following regex: ^\s+version: (.+);$
Note hat the intent is not to replace the version number with a fixed new version, but to increment the existing version.
Ideally, the increment logic would handle version strings representing either [version] (System.Version) or [semver] (System.Management.Automation.SemanticVersion) instances, ranging from 2 - 4 components; e.g.:
1.01.0.21.0.2.3-[version]format (up to 4 numeric components)1.0.2-preview2-[semver]format (up to 3 numeric components), optionally with a--separated preview label1.0.2-preview2+001- ditto, additionally with a+-separated build label
回答1:
In PowerShell [Core] (v6.1+), a concise solution is possible:
$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
Note:
* In PowerShell [Core] 6+, BOM-less UTF-8 is the default encoding; use -Encoding with Set-Content if you need a different encoding.
* By using -Raw, the command reads the entire file into memory first, which enables writing back to that same file in the same pipeline; however, there is a slight risk of data loss if writing back to the input file gets interrupted.
* -replace invariably replaces all substrings that match the regex.
* Inline regex option (?m) ensures that ^ and $ match the start and end of individual lines, which is necessary due to Get-Content -Raw reading the entire file as a single, multi-line string.
Note:
For simplicity, text-based manipulation of the version string is performed, but you could also cast
$_.Valueto[version]or[semver](PowerShell [Core] v6+ only) and work with that.
The advantage of the text-based manipulation is the concise ability to retain all other components of the input version string as-is, without adding previously unspecified ones.The above relies on the -replace operator's ability to perform regex-based string substitutions fully dynamically, via a script block (
{ ... }) - as explained in this answer.The regexes use look-around assertions (
(?<=...)and(?=...)) so as to ensure that only the part of the input to be modified is matched.- Only the
(?<=^\s+version: )and(?=;$)look-arounds are specific to the sample file format; adjust these parts as needed to match the version number in your file format.
- Only the
The above increment's the input version's last numeric component. To target the various version-number components, use the following inner regex instead:
Increment the major number (e.g.,
2.0.9->3.0.9):'2.0.9' -replace '\d+(?=\..+)', { 1 + [int] $_.Value }
The minor number:
'2.0.9' -replace '(?<=^\d+\.)\d+(?=.*)', { 1 + [int] $_.Value }
The patch / build number (3rd component;
2.0.9->2.0.10):'2.0.9' -replace '(?<=^\d+\.\d+\.)\d+(?=.*)', { 1 + [int] $_.Value }
The last / revision number, as above, whatever it is, even if followed by a pre-release label (e.g.,;
2.0.9.10->2.0.9.11or7.0.0-preview2->7.0.1-preview2):'2.0.9.10' -replace '(?<=\.)\d+(?=$|-)', { 1 + [int] $_.Value }
Note: If the targeted component doesn't exist, the original version is returned as-is.
In Windows PowerShell, where -replace doesn't support script-block-based substitutions, you can use the switch statement with the -File and -Regex options instead:
$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
来源:https://stackoverflow.com/questions/60651450/increment-a-version-number-contained-in-a-text-file