我正在尝试获取发行说明的第一块...
(请参阅代码中的示例内容)
只要我使用简单的方法,它就会起作用,
它只会在我尝试
跨多行(\n
搜索。
我使用(Get-Content $changelog | Out-String)
是因为它会返回1个字符串,而不是每行的一个数组。
$changelog = 'C:\Source\VSTS\AcmeLab\AcmeLab Core\changelog.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.
更新:
使用options ..
$changelog = 'C:\Source\VSTS\AcmeLab\AcmeLab Core\changelog.md'
$regex = '(?smi)([Vv][0-9]+\.[0-9]+\.[0-9]+\n)(^-.*$\n)+'
Get-Content -Path $changelog -Raw | Select-String -Pattern $regex -AllMatches
我也一无所获。(无论我使用\n
还是\r\n
)
答案 0 :(得分:2)
Get-Content -Raw
作为单个字符串读取整个文件会更简单有效。此外,Out-String
在字符串中添加了额外的换行符。-match
运算符-不需要Select-String
的{{1}}开关。
-AllMatches
,但是如果已经将整个文件读入内存,则使用Select-String
运算符会更有效。因此,以下内容将返回第一个块(如果有):
-match
* if ((Get-Content -Raw $changelog) -match '(?m)^v\d+\.\d+\.\d+.*(\r?\n-\s?.*)+') {
# Match found - output it.
$Matches[0]
}
打开内联正则表达式选项(?m)
(多行),这会导致锚点m
和^
与< em>单独的行,而不是整个字符串。
* $
匹配CRLF和仅LF的换行符。
*您可以通过使\r?\n
子表达式为 non-captureing 来使正则表达式稍微更有效,因为您对它捕获的内容不感兴趣:(...)
。
请注意,(?:...)
本身返回一个 Boolean (带有标量LHS),但是有关匹配项的信息记录在自动-match
哈希表变量中,其变量{{1 }}条目包含整体匹配项。
关于您尝试过的事情:
$Matches
不起作用,因为默认情况下0
仅在输入字符串的最后,在 last 行的末尾匹配(尽管可能在最后的换行符之前)。
要使'([Vv][0-9]+\.[0-9]+\.[0-9]+\n)(^-.*$\n)+'
匹配每行的结尾,您必须打开多行正则表达式选项(这是您第二次尝试中所做的)。
结果,没有匹配。
$
不能按预期工作,因为通过使用选项$
(单行),您已经使'(?smi)([Vv][0-9]+\.[0-9]+\.[0-9]+\n)(^-.*$\n)+'
也匹配了换行符,因此,贪婪的子表达式例如因为s
将跨行匹配字符串的其余部分。
结果,从第一个区块开始的所有比赛都结束了。