Reading and updating a stream

I have a small utility that searches multiple files. I had to create it because Google and Windows searches did not find matching lines in the files. The search works great (I'm ready to improve it), but one of the things I'd like to add to my utility is batch search / replace.

So what would be the best way to read a line from a file, compare it to a search term, and if it gets through, then update the line and continue with the rest of the file?

0


source to share


2 answers


I would do the following for each file:

  • Search as usual. Also check if the token replaces. Once you see this, run this file again. If you don't see the replacement token, you're done.
  • When you start over, create a new file and copy every line you read from the input file, doing the replacement as you go.
  • When you're done with the file:
    • Move current file to backup filename
    • Move new file to original file name
    • Delete backup file


Be careful that you don't do this in binaries, etc., although the consequences of text search and replace in binaries would usually be dire!

+2


source


If PowerShell is an option, the function defined below can be used to find and replace files. For example, to find 'a string'

text files in the current directory, follow these steps:

dir *.txt | FindReplace 'a string'

      

To replace 'a string'

with a different value, just add the new value to the end:

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

      



You can also call it in a single file using 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
}

      

Note that it Select-String

also supports regular matches, but has been limited to a simple match for simplicity;) You can also do a more reliable replacement like Jon , rather than just rewrite the file with new content.

0


source







All Articles