使用powershell和regex查找包含特定字符串的所有文件

时间:2018-08-23 07:36:27

标签: regex powershell

试图查找包含特定程序集信息的所有* .config文件。就我而言,我想查找所有具有System.Net.Http版本4.0.0.0

的配置文件

示例内容如下:

     <dependentAssembly>
        <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf38564e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="5.2.4.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f750a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bfad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="4.0.0.0" />
      </dependentAssembly>

所以我需要该配置文件的位置

开头为: <assemblyIdentity name="System.Net.Http"

结尾于: newVersion="4.0.0.0",它们在相同的 dependentAssembly

在某些行尾(\ r \ n)的行尾和行尾,行可能会有讨厌的空白

感谢任何帮助!

这是我尝试过的:

$dDir = Get-ChildItem -Recurse -File -Filter "*.config" -ErrorAction SilentlyContinue
$dDir |  ?{$_ | Select-String -Pattern "System.Net.Http"} | ?{$_ | Select-String -Pattern "newVersion=\`"4.0.0.0\`""} | select fullname

,但是如果在不同的 dependentAssembly

中找到newVersion="4.0.0.0",也会返回此错误

所以我尝试使用正则表达式(regex noob):

$dDir |  ?{$_ | Select-String -Pattern '(.*)\<assemblyIdentity name=\"System.Net.Http\"(.*)newVersion=\"4.0.0.0\"(.*)' -AllMatches}

但这什么也没返回

2 个答案:

答案 0 :(得分:0)

我正在记录Python代码。我认为您可以在PowerShell中找到等效项。

for match in regex.finditer('(System\.Net\.Http).+?newVersion\=\"(4\.0\.0\.0)',text):
    print (match)

答案 1 :(得分:0)

由于配置文件似乎是xml,因此建议您使用PowerShell的XML功能。
遗憾的是.config文件的片段不完整,并且缺少根标记。

让我们假设它是这样的:

<root>
    <dependentAssembly>
      <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf38564e35" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="5.2.4.0" />
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f750a3a" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="4.0.0.0" />
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bfad364e35" culture="neutral" />
      <bindingRedirect oldVersion="0.0.0.0-999.999.999.999" newVersion="4.0.0.0" />
    </dependentAssembly>
</root>

然后您可以执行以下操作:

$configFiles = Get-ChildItem $path -Recurse -File -Filter "*.config" -ErrorAction SilentlyContinue
foreach ($file in $configFiles) {
    [xml]$XmlDocument = Get-Content -Path $file.FullName

    $test = $XmlDocument.root.dependentAssembly | 
        Where-Object {$_.assemblyIdentity.name -eq 'System.Net.Http' -and $_.bindingRedirect.newVersion -eq '4.0.0.0'} |
        Select-Object @{Name = 'AssemblyName'; Expression = {$_.assemblyIdentity.name}}, 
                      @{Name = 'Version'; Expression = {$_.bindingRedirect.newVersion}}

    if ($null -ne $test) {
        Write-Host $file.FullName
    }
}

使用XPath可能有更简单的方法,但是我对此并不十分熟悉。

但是

如果您必须/确实希望使用正则表达式来执行此操作,可能是因为配置文件包含非“格式良好”的xml,或者您只是对如何使用Select-String构造感兴趣,尝试:

$rx = '(?s)<dependentAssembly>\s*<assemblyIdentity\s+(name\s*=\s*"System\.Net\.Http")[^<]+<bindingRedirect[^<]+(newVersion\s*=\s*"4\.0\.0\.0")\s+/>\s*</dependentAssembly>'

Get-ChildItem -Path D:\test -Recurse -Filter '*.config' | ForEach-Object {
    if ($_ | Get-Content -Raw | Select-String -Pattern $rx -Quiet) {
        Write-Host $_.FullName
    }
}