从Select-String获取行号和行号

时间:2016-03-07 20:18:22

标签: powershell get-childitem select-string

我有这个脚本很好用,但我还需要它来返回行号和行。

如果我这样做

Select-String w:\test\york\*.* -pattern "mistake"

我得到了

W:\test\york\test.html:179:<p>If you notice a mistake on an information slip, contact the employer, payer, or administrator for that slip.</p>
W:\test\york\test.html:180:<p>If you notice a mistake in the tax-related information or have an account-specific question about other tax-related information, call the Individual income tax and trust enquiries line at 1-800-959-8281.</p>

哪个是完美的。但是,在我的脚本中,这是:

param(
    [string]$pattern,
    [string]$path  
) 
$exclude = '*\test\*'
Get-ChildItem -Path $path -Recurse -Filter *.html | Where-Object {
    ForEach-Object {
        if (Get-Content $_.FullName | Select-String -Pattern "<h2>Stay Connected") {
            Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<h2>Stay Connected"
        } elseif (Get-Content $_.FullName | Select-String -Pattern "<h2>Soyez branch") {
            Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<h2>Soyez branch"
        } else {
            Select-String -InputObject (Get-Content $_.FullName | Out-String) -Pattern "(?sm)<main([\w\W]*)$pattern([\w\W]*)<\/main>"
        }
    }
} | Select Fullname | ? {$_.FullName -notlike $exclude}

我只在CSV中获得此结果:

#TYPE Selected.System.IO.FileInfo
FullName
W:\test\york\test.html

如何使用脚本在我的CSV文件中获取简单搜索的结果?

根据Ansgar Wiechers编辑&#39;答案。

$pattern是&#34;教科书&#34;。

这是我目前的代码:

param(
    [string]$pattern,
    [string]$path,
    [string]$name  
) 
$expr = "(?sm)<main([\w\W]*)$pattern([\w\W]*)" +
        '(?:<h2>Stay Connected|<h2>Soyez branch|<\/main>)'
Get-ChildItem -Path $path -Recurse -Filter *.html |
    Select-String -Pattern $expr |
    Select-Object Path, LineNumber, Line |
    Export-Csv "W:\test\search_results\$name.csv" -NoType

如果我更换

$expr = "(?sm)<main([\w\W]*)$pattern([\w\W]*)" +
        '(?:<h2>Stay Connected|<h2>Soyez branch|<\/main>)'

通过

$expr = $pattern

我得到6个结果(这是正确的),但如果我使用Ansgar提供的表达式,我得不到任何结果。为了让表达式正常工作,我错过了什么?

1 个答案:

答案 0 :(得分:3)

不要让事情变得比他们需要的更复杂。

$expr = "(?sm)<main([\w\W]*)$pattern([\w\W]*)" +
        '(?:<h2>Stay Connected|<h2>Soyez branch|<\/main>)'
$files = Get-ChildItem -Path $path -Recurse -Filter *.html
foreach ($filename in $files) {
    Get-Content $filename -Raw |
        Select-String -Pattern $expr } |
        Select-Object @{n='Path';e={$filename}}, LineNumber, Line |
        Export-Csv 'C:\path\to\your.csv' -NoType
}

无需两次检查每个文件。或者使用不同的表达。只需循环遍历Get-ChildItem的输出,将每个文件的内容传送到Select-String,然后选择生成的MatchInfo对象的相关属性。

原则上Select-String甚至可以自己阅读文件。但是,它会将内容作为一个行数组处理,从而阻止多行匹配。因此,您必须使用Get-Content -Raw(或PowerShell v2及更早版本中的Get-Content | Out-String)读取文件,以便将内容整合到一个字符串中。

如果您需要过滤掉包含文件夹test的路径,您应该在Get-ChildItem之后立即执行此操作:

$files = Get-ChildItem -Path $path -Recurse -Filter *.html |
         Where-Object { $_.FullName -notlike $exclude }
foreach ($filename in $files) {
    Get-Content ...
}

从技术上讲,也可以在Select-String后执行此操作:

$files = Get-ChildItem -Path $path -Recurse -Filter *.html
foreach ($filename in $files) {
    ...
        Where-Object { $_.Path -notlike $exclude } |
        Export-Csv 'C:\path\to\your.csv' -NoType
}

然而,在处理后过滤输出是浪费资源,当你也可以过滤输入并避免产生你不想要的结果。