PwSh RegEx 捕获版本信息 - 省略(周围)x(32|64|86) & 32|64(-)位
PwSh RegEx capture Version information - omit (surrounding) x(32|64|86) & 32|64(-)Bit
我很着急,RegEx-tract 一些文件名中的裸版本信息。
例如“1.2.3.4”
假设我有以下文件名:
VendorSetup-x64-1.23.4.exe
VendorSetup-1-2-3-4.exe
Vendor Setup 1.23.456Update.exe
SoftwareName-1.2.34.5-x64.msi
SoftwareName-1.2.3.4-64bit.msi
SoftwareName-64-Bit-1.2.3.4.msi
VendorName_SoftwareName_64_1.2.3_Setup.exe
(我知道那里还有一些文件名,其中包含“x32”和“x86”,所以我将它们添加到标题中)
首先,我将 _
和 -
替换为 .
,我通常希望避免这种情况,但还没有找到一个更聪明的方法,说实话 - 只有在字符串中没有其他“数字”信息时才有效,例如第二个文件名。
然后我尝试使用像
这样的正则表达式来提取版本信息
-replace '^(?:\D+)?(\d+((\.\d+){1,4})?)(?:.*)?', ''
无法省略“x64”、“64Bit”、“64-Bit”或一般情况下的任何变体。
此外,我还玩过正则表达式,例如
-replace '^(?:[xX]*\d{2})?(?:\D+)?(\d+((\.\d+){1,4})?)(?:.*)?$', ''
尝试省略前导“x64”或“64”,但没有成功(很可能是因为从 -
替换为 .
。
在事情变得更糟之前,我想问一下是否有人可以帮助我或引导我朝着正确的方向前进?
提前致谢!
这可以使用单一模式来完成,但通过将其拆分为两个单独的模式并让 PowerShell 完成一些工作,整体解决方案会容易得多。
模式 1 匹配由 .
(点)分隔的版本号:
(?<=[\s_-])\d+(?:\.\d+){1,3}
模式 2 匹配由 -
(破折号)分隔的版本号:
(?<=[\s_-])\d+(?:-\d+){1,3}
模式以 (?<=[\s_-])
开头,这是一个积极的后视断言,可确保版本由左侧的 space、下划线或短划线分隔,而不会将这些包含在捕获的值中.这可以防止第一个样本中的子字符串 64-1 作为一个版本进行匹配。
可以在 regex101.
中找到该模式的详细说明
Powershell代码:
# Create an array of sample filenames
$names = @'
VendorSetup-2022-05-x64-1.23.4.exe
VendorSetup-x64-1.23.4-2022-05.exe
VendorSetup-1-2-3-4.exe
VendorSetup_2022-05_1-2-3-4.exe
Vendor Setup 1.23.456Update.exe
SoftwareName-1.2.34.5-x64.msi
SoftwareName-1.2.3.4-64bit.msi
SoftwareName-64-Bit-1.2.3.4.msi
VendorName_SoftwareName_64_1.2.3_Setup.exe
NoVersion.exe
'@ -split '\r?\n'
# Array of RegEx patterns in order of precedence.
$versionPatterns = '(?<=[\s_-])\d+(?:\.\d+){1,3}', # 2..4 numbers separated by '.'
'(?<=[\s_-])\d+(?:-\d+){1,3}' # 2..4 numbers separated by '-'
foreach( $name in $names ) {
$version = $versionPatterns.
ForEach{ [regex]::Match( $name, $_, 'RightToLeft' ).Value }. # Apply each pattern from right to left of string.
Where({ $_ }, 'First'). # Get first matching pattern (non-empty value).
ForEach{ $_ -replace '\D+', '.' }[0] # Normalize the number separator and get single string.
# Output custom object for nice table formatting
[PSCustomObject]@{ Name = $name; Version = $version }
}
输出:
Name Version
---- -------
VendorSetup-2022-05-x64-1.23.4.exe 1.23.4
VendorSetup-x64-1.23.4-2022-05.exe 1.23.4
VendorSetup-1-2-3-4.exe 1.2.3.4
VendorSetup_2022-05_1-2-3-4.exe 1.2.3.4
Vendor Setup 1.23.456Update.exe 1.23.456
SoftwareName-1.2.34.5-x64.msi 1.2.34.5
SoftwareName-1.2.3.4-64bit.msi 1.2.3.4
SoftwareName-64-Bit-1.2.3.4.msi 1.2.3.4
VendorName_SoftwareName_64_1.2.3_Setup.exe 1.2.3
NoVersion.exe
Powershell代码解释:
- 为了解决歧义 当一个文件名有多个模式匹配时,我们使用以下规则:
- 带有
.
分隔符的版本优于带有 -
分隔符的版本。我们只需按此顺序应用模式,并在第一个模式匹配时停止。
- 首选最右边的版本(通过将
RightToLeft
标志传递给 [regex]::Match()
)。
.ForEach
和 .Where
是 PowerShell intrinsic methods。它们基本上是 ForEach-Object
和 Where-Object
cmdlet 的更快变体。
- 最后一个
.ForEach
之后的索引 [0]
运算符是必需的,因为 .ForEach
和 .Where
总是 return 数组,即使只有一个值,与行为 cmdlets 相反。
我很着急,RegEx-tract 一些文件名中的裸版本信息。 例如“1.2.3.4”
假设我有以下文件名:
VendorSetup-x64-1.23.4.exe
VendorSetup-1-2-3-4.exe
Vendor Setup 1.23.456Update.exe
SoftwareName-1.2.34.5-x64.msi
SoftwareName-1.2.3.4-64bit.msi
SoftwareName-64-Bit-1.2.3.4.msi
VendorName_SoftwareName_64_1.2.3_Setup.exe
(我知道那里还有一些文件名,其中包含“x32”和“x86”,所以我将它们添加到标题中)
首先,我将 _
和 -
替换为 .
,我通常希望避免这种情况,但还没有找到一个更聪明的方法,说实话 - 只有在字符串中没有其他“数字”信息时才有效,例如第二个文件名。
然后我尝试使用像
这样的正则表达式来提取版本信息-replace '^(?:\D+)?(\d+((\.\d+){1,4})?)(?:.*)?', ''
无法省略“x64”、“64Bit”、“64-Bit”或一般情况下的任何变体。
此外,我还玩过正则表达式,例如
-replace '^(?:[xX]*\d{2})?(?:\D+)?(\d+((\.\d+){1,4})?)(?:.*)?$', ''
尝试省略前导“x64”或“64”,但没有成功(很可能是因为从 -
替换为 .
。
在事情变得更糟之前,我想问一下是否有人可以帮助我或引导我朝着正确的方向前进?
提前致谢!
这可以使用单一模式来完成,但通过将其拆分为两个单独的模式并让 PowerShell 完成一些工作,整体解决方案会容易得多。
模式 1 匹配由 .
(点)分隔的版本号:
(?<=[\s_-])\d+(?:\.\d+){1,3}
模式 2 匹配由 -
(破折号)分隔的版本号:
(?<=[\s_-])\d+(?:-\d+){1,3}
模式以 (?<=[\s_-])
开头,这是一个积极的后视断言,可确保版本由左侧的 space、下划线或短划线分隔,而不会将这些包含在捕获的值中.这可以防止第一个样本中的子字符串 64-1 作为一个版本进行匹配。
可以在 regex101.
中找到该模式的详细说明Powershell代码:
# Create an array of sample filenames
$names = @'
VendorSetup-2022-05-x64-1.23.4.exe
VendorSetup-x64-1.23.4-2022-05.exe
VendorSetup-1-2-3-4.exe
VendorSetup_2022-05_1-2-3-4.exe
Vendor Setup 1.23.456Update.exe
SoftwareName-1.2.34.5-x64.msi
SoftwareName-1.2.3.4-64bit.msi
SoftwareName-64-Bit-1.2.3.4.msi
VendorName_SoftwareName_64_1.2.3_Setup.exe
NoVersion.exe
'@ -split '\r?\n'
# Array of RegEx patterns in order of precedence.
$versionPatterns = '(?<=[\s_-])\d+(?:\.\d+){1,3}', # 2..4 numbers separated by '.'
'(?<=[\s_-])\d+(?:-\d+){1,3}' # 2..4 numbers separated by '-'
foreach( $name in $names ) {
$version = $versionPatterns.
ForEach{ [regex]::Match( $name, $_, 'RightToLeft' ).Value }. # Apply each pattern from right to left of string.
Where({ $_ }, 'First'). # Get first matching pattern (non-empty value).
ForEach{ $_ -replace '\D+', '.' }[0] # Normalize the number separator and get single string.
# Output custom object for nice table formatting
[PSCustomObject]@{ Name = $name; Version = $version }
}
输出:
Name Version
---- -------
VendorSetup-2022-05-x64-1.23.4.exe 1.23.4
VendorSetup-x64-1.23.4-2022-05.exe 1.23.4
VendorSetup-1-2-3-4.exe 1.2.3.4
VendorSetup_2022-05_1-2-3-4.exe 1.2.3.4
Vendor Setup 1.23.456Update.exe 1.23.456
SoftwareName-1.2.34.5-x64.msi 1.2.34.5
SoftwareName-1.2.3.4-64bit.msi 1.2.3.4
SoftwareName-64-Bit-1.2.3.4.msi 1.2.3.4
VendorName_SoftwareName_64_1.2.3_Setup.exe 1.2.3
NoVersion.exe
Powershell代码解释:
- 为了解决歧义 当一个文件名有多个模式匹配时,我们使用以下规则:
- 带有
.
分隔符的版本优于带有-
分隔符的版本。我们只需按此顺序应用模式,并在第一个模式匹配时停止。 - 首选最右边的版本(通过将
RightToLeft
标志传递给[regex]::Match()
)。
- 带有
.ForEach
和.Where
是 PowerShell intrinsic methods。它们基本上是ForEach-Object
和Where-Object
cmdlet 的更快变体。- 最后一个
.ForEach
之后的索引[0]
运算符是必需的,因为.ForEach
和.Where
总是 return 数组,即使只有一个值,与行为 cmdlets 相反。