如何使用Powershell查找替换多个文本文件中的多个字符串

时间:2014-08-06 15:11:38

标签: regex powershell optimization replace find

我不熟悉脚本和Powershell。我最近一直在做一些研究,并尝试构建一个脚本来查找/替换一堆文本文件中的文本(每个文本文件都有代码,不超过4000行)。但是,我想将FindString和ReplaceString保留为变量,因为有多个值,而这些值又可以从单独的csv文件中读取。

我已经提出了这个功能正常的代码,但我想知道这是否是上述要求的最佳解决方案。我想将FindString和ReplaceString保持为在脚本中兼容的正则表达式,因为我还想查找/替换模式。 (我还没有用正则表达式模式测试它)

Input.csv的示例内容:( csv中的对象数量可能在50到500之间)

FindString  ReplaceString
AA1A    171PIT9931A
BB1B    171PIT9931B
CC1C    171PIT9931E
DD1D    171PIT9932A
EE1E    171PIT9932B
FF1F    171PIT9932E
GG1G    171PIT9933A

守则

$Iteration = 0
$FDPATH = 'D:\opt\HMI\Gfilefind_rep'
#& 'D:\usr\fox\wp\bin\tools\fdf_g.exe' $FDPATH\*.fdf
$GraphicsList = Get-ChildItem -Path $FDPATH\*.g | ForEach-Object FullName
$FindReplaceList = Import-Csv -Path $FDPATH\Input.csv
foreach($Graphic in $Graphicslist){
    Write-Host "Processing Find Replace on : $Graphic"
    foreach($item in $FindReplaceList){
    Get-Content $Graphic | ForEach-Object { $_ -replace "$($item.FindString)", "$($item.ReplaceString)" } | Set-Content ($Graphic+".tmp")
        Remove-Item $Graphic
        Rename-Item ($Graphic+".tmp") $Graphic
        $Iteration = $Iteration +1
        Write-Host "String Replace Completed for $($item.ReplaceString)"
    }
}

我已经在Stackoverflow中查看了其他帖子,并根据代码的构建收集了有价值的输入。 This post from Ivo Bosticky非常接近我的要求,但我必须在嵌套的foreach循环中执行相同的操作,将查找/替换字符串作为从外部源读取的变量。

总结一下,

  1. 我想知道上面的代码是否可以优化 执行,因为我觉得执行需要很长时间。 (我更喜欢 现在不使用别名,因为我刚开始,很好 使用长而实用的脚本而不是简洁的脚本 很难理解)
  2. 我想补充一下正在进行的迭代次数 循环。我能够将当前的迭代次数添加到 控制台,但无法想象如何管道输出 Measure-Command到变量,可以在Write-Host中使用 命令。我还想显示代码所用的时间 执行完成后。
  3. 感谢您阅读此查询所花费的时间。非常感谢您的支持!

1 个答案:

答案 0 :(得分:0)

首先,除非您的替换字符串将包含换行符(这将改变行边界),否则我建议只获取并设置每个$Graphic文件的内容一次,并进行所有替换一次通过。这也将导致更少的文件重命名和删除。

其次,将$item.FindString$item.ReplaceString直接传递给-replace运算符而不是调用模板引擎将值注入字符串文字中会更快(可能略微)。 / p>

第三,除非你真的需要输出直接进入控制台而不是转到正常的输出流,否则我会避免使用Write-Host。请参阅Write-Host Considered Harmful

第四,您可能实际上想要删除每次查找和替换时调用的Write-Host,因为它可能会对整个执行时间产生相当大的影响,具体取决于有多少替换。

你最终会得到这样的东西:

$timeTaken = (measure-command {
    $Iteration = 0
    $FDPATH = 'D:\opt\HMI\Gfilefind_rep'
    #& 'D:\usr\fox\wp\bin\tools\fdf_g.exe' $FDPATH\*.fdf
    $GraphicsList = Get-ChildItem -Path $FDPATH\*.g | ForEach-Object FullName
    $FindReplaceList = Import-Csv -Path $FDPATH\Input.csv
    foreach($Graphic in $Graphicslist){
        Write-Output "Processing Find Replace on : $Graphic"
        Get-Content $Graphic | ForEach-Object { 
        foreach($item in $FindReplaceList){
            $_ = $_ -replace $item.FindString, $item.ReplaceString
        }       
        $Iteration += 1
        $_
        } | Set-Content ($Graphic+".tmp")
        Remove-Item $Graphic
        Rename-Item ($Graphic+".tmp") $Graphic
    }
}).TotalMilliseconds

我还没有对它进行测试,但它应该运行得更快,而且它会将经过的时间保存到变量中。