在 powershell 中按正则表达式中的命名捕获组排序
Sort by named capture group within regular expression in powershell
我有一个正则表达式定义如下:
$regexpo = "^Amma\s(?'version'(\d+\.){3}\d)\.zip$"
上面的表达式有一个带有组的标签 - (\d+.){3}\d)
我是这样使用的:
$Library = $wholeContent |
Where-Object { $_.Name -match $regexpo } |
Sort-Object Name -Descending
但我想改为按定义的正则表达式中的标记组对其进行排序,它代表版本号。
按正则表达式匹配排序的简单示例,按最后一个字符。
echo a3 b2 c1 | sort { $_ -match "(?'last'.$)"; $matches.last }
c1
b2
a3
将Sort-Object
与计算的属性(为每个输入对象评估的脚本块({ ... }
)一起使用,反映在$_
中)如下:
# Sample input
$wholeContent =
[pscustomobject] @{ Name = 'Amma 10.0.0.1.zip'; Type = '...' },
[pscustomobject] @{ Name = 'Not a match' ; Type = '...' },
[pscustomobject] @{ Name = 'Amma 1.0.0.2.zip' ; Type = '...' },
[pscustomobject] @{ Name = 'Amma 2.1.2.3.zip' ; Type = '...' }
# Define the regex that matches the full name
# and captures the embedded version number in named capture group 'version'.
# Better to use '...' (single quotes) to define regexes, to prevent
# confusion with string expansion inside "..."
# Note the alternate syntax `<version>` instead of `'version'`.
$regex = '^Amma\s(?<version>(\d+\.){3}\d+)\.zip$'
# Filter by the line of interest, then sort by the extracted version number.
# Automatic variable $Matches is a hashtable that contains the results of
# the regex match, with entry 'version' containing the capture group's value.
# Casting to [version] ensures that version-appropriate sorting is used.
$wholeContent |
Where-Object { $_.Name -match $regex } |
Sort-Object { [version] ($_.Name -replace $regex, '${version}') }
注意这里需要匹配两次[1]:一次过滤感兴趣的行,再提取一次嵌入版本文本,通过 .
注意:可以在此处使用 -replace
和原始正则表达式,因为手头的正则表达式旨在匹配 整个 输入字符串, 它允许仅用命名捕获组的值 (${version}
) 替换整个字符串以仅产生后者;更详细的替代方法是使用另一个 -match
操作通过 $Matches
:
获取捕获组值
$null = $_.Name -match $regex; $Matches['version']
上面的结果如下,表明只提取了感兴趣的行,按版本号正确排序:
Name Type
---- ----
Amma 1.0.0.2.zip ...
Amma 2.1.2.3.zip ...
Amma 10.0.0.1.zip ...
[1] 虽然 automatic $Matches
variable 由 -match
操作填充,但 在后续管道段的脚本块中可用 原则上,允许访问匹配操作的结果,这里不能使用它,因为 Sort-Object
必须是一个 aggregating cmdlet;也就是说,它必须先 收集所有输入 才能执行排序,此时使用 $Matches
在计算的 属性 中只包含 最后 个输入对象的匹配项。
我有一个正则表达式定义如下:
$regexpo = "^Amma\s(?'version'(\d+\.){3}\d)\.zip$"
上面的表达式有一个带有组的标签 - (\d+.){3}\d)
我是这样使用的:
$Library = $wholeContent |
Where-Object { $_.Name -match $regexpo } |
Sort-Object Name -Descending
但我想改为按定义的正则表达式中的标记组对其进行排序,它代表版本号。
按正则表达式匹配排序的简单示例,按最后一个字符。
echo a3 b2 c1 | sort { $_ -match "(?'last'.$)"; $matches.last }
c1
b2
a3
将Sort-Object
与计算的属性(为每个输入对象评估的脚本块({ ... }
)一起使用,反映在$_
中)如下:
# Sample input
$wholeContent =
[pscustomobject] @{ Name = 'Amma 10.0.0.1.zip'; Type = '...' },
[pscustomobject] @{ Name = 'Not a match' ; Type = '...' },
[pscustomobject] @{ Name = 'Amma 1.0.0.2.zip' ; Type = '...' },
[pscustomobject] @{ Name = 'Amma 2.1.2.3.zip' ; Type = '...' }
# Define the regex that matches the full name
# and captures the embedded version number in named capture group 'version'.
# Better to use '...' (single quotes) to define regexes, to prevent
# confusion with string expansion inside "..."
# Note the alternate syntax `<version>` instead of `'version'`.
$regex = '^Amma\s(?<version>(\d+\.){3}\d+)\.zip$'
# Filter by the line of interest, then sort by the extracted version number.
# Automatic variable $Matches is a hashtable that contains the results of
# the regex match, with entry 'version' containing the capture group's value.
# Casting to [version] ensures that version-appropriate sorting is used.
$wholeContent |
Where-Object { $_.Name -match $regex } |
Sort-Object { [version] ($_.Name -replace $regex, '${version}') }
注意这里需要匹配两次[1]:一次过滤感兴趣的行,再提取一次嵌入版本文本,通过
注意:可以在此处使用 -replace
和原始正则表达式,因为手头的正则表达式旨在匹配 整个 输入字符串, 它允许仅用命名捕获组的值 (${version}
) 替换整个字符串以仅产生后者;更详细的替代方法是使用另一个 -match
操作通过 $Matches
:
获取捕获组值
$null = $_.Name -match $regex; $Matches['version']
上面的结果如下,表明只提取了感兴趣的行,按版本号正确排序:
Name Type
---- ----
Amma 1.0.0.2.zip ...
Amma 2.1.2.3.zip ...
Amma 10.0.0.1.zip ...
[1] 虽然 automatic $Matches
variable 由 -match
操作填充,但 在后续管道段的脚本块中可用 原则上,允许访问匹配操作的结果,这里不能使用它,因为 Sort-Object
必须是一个 aggregating cmdlet;也就是说,它必须先 收集所有输入 才能执行排序,此时使用 $Matches
在计算的 属性 中只包含 最后 个输入对象的匹配项。