如何选择字符串多行?

时间:2019-03-27 09:18:35

标签: powershell select-string

我正在尝试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"

2 个答案:

答案 0 :(得分:1)

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
}

答案 1 :(得分:0)

Select-String对其输入对象单独 进行操作,并且如果您直接将文件路径传递给它(通过-Path或{{ 1}}),或者您通过管道-LiteralPath的输出,对每条执行匹配。

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

Get-Content -Raw

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


通过对比,如果您要保留每行匹配但还捕获固定数量的环绕线 ,请使用Get-Content -Raw file.txt | Select-String -Pattern Line1 参数。

.Line

Ansgar Wiechers' helpful answer显示了如何从结果中提取所有行。