2008-12-04 55 views
0

我有一个小工具,可以搜索多个文件。我不得不创建它,因为两个谷歌& Windows桌面搜索没有找到适当的文件行。搜索工作正常(我愿意改进它),但我想添加到我的实用程序中的一件事是批量查找/替换。阅读和更新文件流

那么如何从文件中读取一行,将其与搜索项进行比较,如果它通过,然后更新行并继续执行文件的其余部分,最好的方法是?

回答

2

我会做对每个文件执行以下操作:

  • 执行搜索为正常。同时检查要替换的令牌。一旦你看到它,再次启动该文件。如果您没有看到要替换的令牌,则说明您已完成。
  • 当您再次开始时,创建一个新文件并复制您从输入文件中读取的每一行,并随时进行替换。
  • 当你完成的文件:
    • 移动当前文件到备份文件名
    • 将新的文件到原来的文件名
    • 删除备份文件

小心你不要在二进制文件等上做这件事 - 做文本搜索和替换二进制文件的后果通常是可怕的!

+0

有一个权衡。如果您知道这些文件最有可能具有SearchTerm,则最好在开始临时文件时复制其他文件的内容。而不是通过文件搜索两次。 – grepsedawk 2008-12-04 22:17:58

0

如果PowerShell是一个选项,下面定义的函数可用于执行跨文件的查找和替换。例如,要查找文本文件'a string'在当前目录下,你会怎么做:

dir *.txt | FindReplace 'a string' 

要使用另一个值替换'a string',只是在末尾添加新值:

dir *.txt | FindReplace 'a string' 'replacement string' 

你可以也可以使用FindReplace -path MyFile.txt 'a string'在单个文件中调用它。

function FindReplace([string]$search, [string]$replace, [string[]]$path) { 
    # Include paths from pipeline input. 
    $path += @($input) 

    # Find all matches in the specified files. 
    $matches = Select-String -path $path -pattern $search -simpleMatch 

    # If replacement value was given, perform replacements. 
    if($replace) { 
    # Group matches by file path. 
    $matches | group -property Path | % { 
     $content = Get-Content $_.Name 

     # Replace all matching lines in current file. 
     foreach($match in $_.Group) { 
     $index = $match.LineNumber - 1 
     $line = $content[$index] 
     $updatedLine = $line -replace $search,$replace 
     $content[$index] = $updatedLine 

     # Update match with new line value. 
     $match | Add-Member NoteProperty UpdatedLine $updatedLine 
     } 

     # Update file content. 
     Set-Content $_.Name $content 
    } 
    } 

    # Return matches. 
    $matches 
} 

注意Select-String还支持正则表达式匹配,但一直constrainted简单的比赛为简单;)您也可以执行一个更强大的替代喜欢Jon建议,而不是仅仅覆盖具有新内容的文件。