我正在尝试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"
答案 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
仅在它们之间插入换行符 行(不在最后一行的末尾)。但是,可以修改每个片段以产生与另一个相同的结果。修剪第一个示例中的字符串以删除结尾的换行符,或将另一个换行符添加到第二个示例的字符串中。
如果要将输出作为单独的行,只需输出Line
和PostContext
属性,而不将它们合并为一个字符串:
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显示了如何从结果中提取所有行。