如何选择字符串多行?



我正在尝试Select-String多行的文本。

例:

"This is line1
<Test>Testing Line 2</Test>
<Test>Testing Line 3</Test>"

我希望能够在Select-String中选择所有 3 行。但是,它仅在我执行Select-String -Pattern "Line1"时选择第一行。如何将所有 3 行提取在一起?

Select-String -Pattern "Line1"

>Select-String单独对其输入对象进行操作,如果您将文件路径直接传递给它(通过-Path-LiteralPath),或者从Get-Content通过管道输出,则在每上执行匹配。

因此,将您的输入作为单个多行字符串传递,如果它来自文件,则最容易通过Get-Content -Raw(PSv3+) 实现:

Get-Content -Raw file.txt | Select-String -Pattern Line1

请注意,这意味着如果模式匹配,则输出文件的整个内容,可通过输出对象的.Line属性访问。


相比之下,如果要保留每行匹配,但同时捕获固定数量的周围线条请使用-Context参数。

Get-Content file.txt | Select-String -Pattern Line1 -Context 0, 2

Ansgar Wiechers的有用答案显示了如何从结果中提取所有线条。

Select-String允许通过参数-Context在匹配行之前或之后选择给定数量的行。-Context 2,0选择前面的 2 行,-Context 0,2选择后面的 2 行,-Context 2,2选择匹配前的 2 行以及匹配后的 2 行。

但是,您不会在一个大块中获得匹配行和上下文行,因此如果您希望将它们作为单个字符串,则需要将它们组合在一起:

Select-String -Pattern 'Line1' -Context 0,2 | ForEach-Object {
$($_.Line; $_.Context.PostContext) | Out-String
}

正如@mklement0评论中正确指出的那样,上面的内容相对较慢,如果您只处理几个匹配项,这不是问题,但如果您需要处理数百或数千个匹配项,则会出现问题。若要提高性能,可以将值合并到单个数组中,并使用-join运算符:

Select-String -Pattern 'Line1' -Context 0,2 | ForEach-Object {
(,$_.Line + $_.Context.PostContext) -join [Environment]::NewLine
}

请注意,这两个代码片段不会产生完全相同的结果,因为Out-String在每一行(包括最后一行)附加一个换行符,而-join只在行之间放置换行符(而不是在最后一行的末尾)。但是,可以修改每个代码段以产生与另一个代码段相同的结果。修剪第一个示例中的字符串以删除尾随换行符,或将另一个换行符附加到第二个示例中的字符串。

如果您希望输出为单独的行,只需输出LinePostContext属性,而无需将它们合并到一个字符串中:

Select-String -Pattern 'Line1' -Context 0,2 | ForEach-Object {
$_.Line
$_.Context.PostContext
}

相关内容

  • 没有找到相关文章

最新更新