Powershell中的Regex无法检查换行符

时间:2018-10-03 19:00:59

标签: regex powershell

我正在尝试获取发行说明的第一块...
(请参阅代码中的示例内容)

只要我使用简单的方法,它就会起作用,
它只会在我尝试 跨多行(\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

1 个答案:

答案 0 :(得分:2)

  • 除非您对PowerShell v2有所了解,否则使用Get-Content -Raw作为单个字符串读取整个文件会更简单有效。此外,Out-String在字符串中添加了额外的换行符。
  • 由于您只想查找 first 匹配项,因此可以使用-match运算符-不需要Select-String的{​​{1}}开关。
    • 注意:虽然您可以不使用-AllMatches,但是如果已经将整个文件读入内存,则使用Select-String运算符会更有效。
  • 默认情况下,
  • 正则表达式匹配在PowerShell中始终不区分大小写 ,这与PowerShell的整体不区分大小写一致。

因此,以下内容将返回第一个块(如果有):

-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将跨行匹配字符串的其余部分。 结果,从第一个区块开始的所有比赛都结束了。