我正在尝试获取发行说明的第一个块...
(请参阅代码中的示例内容(
每当我使用简单的东西时,它都可以工作,
只有当我尝试 跨多行搜索 (n
(。
我正在使用(Get-Content $changelog | Out-String)
因为它返回 1 个字符串而不是每行的数组。
$changelog = 'C:SourceVSTSAcmeLabAcmeLab Corechangelog.md'
$regex = '([Vv][0-9]+.[0-9]+.[0-9]+n)(^-.*$n)+'
(Get-Content $changelog | Out-String) | Select-String -Pattern $regex -AllMatches
<#
SAMPLE:
------
v1.0.23
- Adds an IContainer API.
- Bugfixes.
v1.0.22
- Hotfix: Language operators.
v1.0.21
- Support duplicate query parameters.
v1.0.20
- Splitting up the ICommand interface.
- Fixing the referrer header empty field value.
#>
我需要的结果是:
v1.0.23
- Adds an IContainer API.
- Bugfixes.
更新:
使用选项..
$changelog = 'C:SourceVSTSAcmeLabAcmeLab Corechangelog.md'
$regex = '(?smi)([Vv][0-9]+.[0-9]+.[0-9]+n)(^-.*$n)+'
Get-Content -Path $changelog -Raw | Select-String -Pattern $regex -AllMatches
我也一无所获..(无论我使用n
还是rn
(
- 除非你坚持使用 PowerShell v2,否则使用
Get-Content -Raw
将整个文件作为单个字符串读取会更简单、更高效;此外,Out-String
会为字符串添加一个额外的换行符。[1] - 由于您只查找第一个匹配项,因此您可以使用
-match
运算符 - 无需Select-String
的-AllMatches
开关。- 注意:虽然您可以在没有它的情况下使用
Select-String
,但使用-match
运算符更有效,因为您已经将整个文件读入内存。
- 注意:虽然您可以在没有它的情况下使用
- 默认情况下,正则表达式匹配在 PowerShell 中始终不区分大小写,与 PowerShell 的整体不区分大小写一致。
因此,以下内容返回第一个块(如果有(:
if ((Get-Content -Raw $changelog) -match '(?m)^vd+.d+.d+.*(r?n-s?.*)+') {
# Match found - output it.
$Matches[0]
}
*(?m)
打开内联正则表达式选项m
(多行(,这会导致锚点^
和$
匹配单个行的开头和结尾,而不是整个字符串的开头和结尾。
r?n
匹配 CRLF 和仅 LF 换行符。- 您可以通过使
(...)
子表达式不捕获来使正则表达式稍微更有效率,因为您对它捕获的内容不感兴趣:(?:...)
.
请注意,-match
本身返回一个布尔值(带有标量 LHS(,但有关匹配的信息记录在自动$Matches
哈希表变量中,其0
条目包含整体匹配。
至于你尝试过的:
'([Vv][0-9]+.[0-9]+.[0-9]+n)(^-.*$n)+'
不起作用,因为默认情况下$
只匹配输入字符串的最后,最后一行的末尾(尽管可能在最后一个换行符之前(。 要使$
匹配每行的末尾,您必须打开多行正则表达式选项(您在第二次尝试中所做的(。 结果,没有什么比拟的了。
'(?smi)([Vv][0-9]+.[0-9]+.[0-9]+n)(^-.*$n)+'
无法按预期工作,因为通过使用选项s
(单行(,您也.
换行符匹配,以便贪婪的子表达式(如.*
(将跨行匹配字符串的其余部分。 结果,从比赛的第一个块开始的一切。
[1] GitHub 问题 #14444 中讨论了这种有问题的行为。