如何使用 Powershell 从多行 Select-String
How to Select-String from Multiple Lines with Powershell
我下面有这个文件test.dat
<category>Games</category>
</game>
<category>Applications</category>
</game>
<category>Demos</category>
</game>
<category>Games</category>
<description>MLB 2002 (USA)</description>
</game>
<category>Bonus Discs</category>
</game>
<category>Multimedia</category>
</game>
<category>Add-Ons</category>
</game>
<category>Educational</category>
</game>
<category>Coverdiscs</category>
</game>
<category>Video</category>
</game>
<category>Audio</category>
</game>
<category>Games</category>
</game>
如何使用 Get-Content
和 Select-String
从上面的文件输入将以下内容输出到终端。使用上面的输入我需要接收这个输出。
<category>Games</category>
</game>
<category>Games</category>
</game>
这是我目前正在使用的命令,但它不起作用。
Get-Content '.\test.dat' | Select-String -pattern '(^\s+<category>Games<\/category>\n^\s+<\/game>$)'
首先,您需要将其作为一个字符串全部读入以进行跨行匹配。
Get-Content '.\test.dat' -Raw
既然你想排除条目,你可以使用这种模式,只抓取那些在
前后没有白色 space 的条目
'(?s)\s+<category>Games\S+\r?\n</game>'
Select 字符串 returns 一个 matchinfo 对象,您需要提取 Matches
属性 的 Value
属性。您可以通过几种不同的方式做到这一点。
Get-Content '.\test.dat' -Raw |
Select-String '(?s)\s+<category>Games\S+\r?\n</game>' -AllMatches |
ForEach-Object Matches | ForEach-Object Value
或
$output = Get-Content '.\test.dat' -Raw |
Select-String '(?s)\s+<category>Games\S+\r?\n</game>' -AllMatches
$output.Matches.Value
或
(Get-Content '.\test.dat' -Raw |
Select-String '(?s)\s+<category>Games\S+\r?\n</game>' -AllMatches).Matches.Value
输出
<category>Games</category>
</game>
<category>Games</category>
</game>
您也可以使用 [regex]
类型加速器。
$str = Get-Content '.\test.dat' -Raw
[regex]::Matches($str,'(?s)\s+<category>Games\S+\r?\n</game>').value
编辑
根据您的附加信息,我的理解是您想删除所有空的游戏类别。我们可以通过使用此处的字符串来大大简化它。
$pattern = @'
<category>Games</category>
</game>
'@
额外的空行是为了捕捉最后的换行符。你也可以这样写
$pattern = @'
<category>Games</category>
</game>\r?\n
'@
现在,如果我们对模式进行替换,您会看到我认为是您对最终结果的期望。
(Get-Content $inputfile -Raw) -replace $pattern
要完成它,您只需将上面的命令放在 Set-Content
命令中即可。由于 Get-Content
命令被括在括号中,因此在写入文件之前将其完全读入内存。
Set-Content -Path $inputfile -Value ((Get-Content $inputfile -Raw) -replace $pattern)
编辑 2
好吧,它似乎在 ISE 中有效,但在 Powershell 控制台中无效。如果你遇到同样的事情,试试这个。
$pattern = '(?s)\s+<category>Games</category>\r?\n\s+</game>'
Set-Content -Path $inputfile -Value ((Get-Content $inputfile -Raw) -replace $pattern)
我下面有这个文件test.dat
<category>Games</category>
</game>
<category>Applications</category>
</game>
<category>Demos</category>
</game>
<category>Games</category>
<description>MLB 2002 (USA)</description>
</game>
<category>Bonus Discs</category>
</game>
<category>Multimedia</category>
</game>
<category>Add-Ons</category>
</game>
<category>Educational</category>
</game>
<category>Coverdiscs</category>
</game>
<category>Video</category>
</game>
<category>Audio</category>
</game>
<category>Games</category>
</game>
如何使用 Get-Content
和 Select-String
从上面的文件输入将以下内容输出到终端。使用上面的输入我需要接收这个输出。
<category>Games</category>
</game>
<category>Games</category>
</game>
这是我目前正在使用的命令,但它不起作用。
Get-Content '.\test.dat' | Select-String -pattern '(^\s+<category>Games<\/category>\n^\s+<\/game>$)'
首先,您需要将其作为一个字符串全部读入以进行跨行匹配。
Get-Content '.\test.dat' -Raw
既然你想排除条目,你可以使用这种模式,只抓取那些在
前后没有白色 space 的条目'(?s)\s+<category>Games\S+\r?\n</game>'
Select 字符串 returns 一个 matchinfo 对象,您需要提取 Matches
属性 的 Value
属性。您可以通过几种不同的方式做到这一点。
Get-Content '.\test.dat' -Raw |
Select-String '(?s)\s+<category>Games\S+\r?\n</game>' -AllMatches |
ForEach-Object Matches | ForEach-Object Value
或
$output = Get-Content '.\test.dat' -Raw |
Select-String '(?s)\s+<category>Games\S+\r?\n</game>' -AllMatches
$output.Matches.Value
或
(Get-Content '.\test.dat' -Raw |
Select-String '(?s)\s+<category>Games\S+\r?\n</game>' -AllMatches).Matches.Value
输出
<category>Games</category>
</game>
<category>Games</category>
</game>
您也可以使用 [regex]
类型加速器。
$str = Get-Content '.\test.dat' -Raw
[regex]::Matches($str,'(?s)\s+<category>Games\S+\r?\n</game>').value
编辑
根据您的附加信息,我的理解是您想删除所有空的游戏类别。我们可以通过使用此处的字符串来大大简化它。
$pattern = @'
<category>Games</category>
</game>
'@
额外的空行是为了捕捉最后的换行符。你也可以这样写
$pattern = @'
<category>Games</category>
</game>\r?\n
'@
现在,如果我们对模式进行替换,您会看到我认为是您对最终结果的期望。
(Get-Content $inputfile -Raw) -replace $pattern
要完成它,您只需将上面的命令放在 Set-Content
命令中即可。由于 Get-Content
命令被括在括号中,因此在写入文件之前将其完全读入内存。
Set-Content -Path $inputfile -Value ((Get-Content $inputfile -Raw) -replace $pattern)
编辑 2
好吧,它似乎在 ISE 中有效,但在 Powershell 控制台中无效。如果你遇到同样的事情,试试这个。
$pattern = '(?s)\s+<category>Games</category>\r?\n\s+</game>'
Set-Content -Path $inputfile -Value ((Get-Content $inputfile -Raw) -replace $pattern)