简体   繁体   English

如何使用 Powershell 从多行中选择字符串

[英]How to Select-String from Multiple Lines with Powershell

I have this file below test.dat我在 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>

How do I use Get-Content and Select-String to output the following to terminal from the input of the file above.如何使用Get-ContentSelect-String到 output 从上面的文件输入到终端。 Using the above input I need to receive this output.使用上面的输入我需要接收这个 output。

            <category>Games</category>
    </game>
            <category>Games</category>
    </game>

This is the command I'm currently using but it isn't working.这是我目前正在使用的命令,但它不起作用。 Get-Content '.\test.dat' | Select-String -pattern '(^\s+<category>Games<\/category>\n^\s+<\/game>$)'

First thing is you need to read it all in as one string to match across lines.首先,您需要将其全部作为一个字符串读取以跨行匹配。

Get-Content '.\test.dat' -Raw

Since it seems you want to exclude the entry with you can use this pattern that grabs only those that don't have white space after and before由于您似乎想排除条目,因此您可以使用此模式仅抓取那些前后没有空格的条目

'(?s)\s+<category>Games\S+\r?\n</game>'

Select string returns a matchinfo object and you need to extract the Value property of the Matches property. Select 字符串返回匹配信息 object 并且您需要提取Matches属性的Value属性。 You can do that a few different ways.你可以通过几种不同的方式做到这一点。

Get-Content '.\test.dat' -Raw |
    Select-String '(?s)\s+<category>Games\S+\r?\n</game>' -AllMatches |
        ForEach-Object Matches | ForEach-Object Value

or或者

$output = Get-Content '.\test.dat' -Raw |
    Select-String '(?s)\s+<category>Games\S+\r?\n</game>' -AllMatches

$output.Matches.Value

or或者

(Get-Content '.\test.dat' -Raw |
    Select-String '(?s)\s+<category>Games\S+\r?\n</game>' -AllMatches).Matches.Value

Output Output

        <category>Games</category>
</game>


        <category>Games</category>
</game>

You could also use [regex] type accelerator.您也可以使用[regex]类型的加速器。

$str = Get-Content '.\test.dat' -Raw

[regex]::Matches($str,'(?s)\s+<category>Games\S+\r?\n</game>').value

EDIT编辑

Based on your additional info, the way I understand it is you want to remove any game categories that are empty.根据您的附加信息,我理解的方式是您要删除任何空的游戏类别。 We can simplify this greatly by using a here string.我们可以通过使用 here 字符串大大简化这一点。

$pattern = @'
        <category>Games</category>
    </game>

'@

The additional blank line is intentional to capture the final newline character.额外的空白行是为了捕获最后的换行符。 You could also write it like this你也可以这样写

$pattern = @'
        <category>Games</category>
    </game>\r?\n
'@

Now if we do a replace on the pattern, you'll see what I believe is what you expect for your final result.现在,如果我们对模式进行替换,您将看到我认为您对最终结果的期望。

(Get-Content $inputfile -Raw) -replace $pattern

And to finish it off you can just put the above command inside a Set-Content command.要完成它,您只需将上述命令放在Set-Content命令中即可。 Since the Get-Content command is enclosed in parenthesis, it is completely read into memory before the file is written to.由于Get-Content命令包含在括号中,因此在写入文件之前将其完全读入 memory。

Set-Content -Path $inputfile -Value ((Get-Content $inputfile -Raw) -replace $pattern)

EDIT 2编辑 2

Well it seems to work in ISE but not in powershell console.好吧,它似乎在 ISE 中有效,但在 powershell 控制台中无效。 In case you encounter the same thing, try this.如果你遇到同样的事情,试试这个。

$pattern = '(?s)\s+<category>Games</category>\r?\n\s+</game>'

Set-Content -Path $inputfile -Value ((Get-Content $inputfile -Raw) -replace $pattern)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM