2008-12-04 64 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建議,而不是僅僅覆蓋具有新內容的文件。