none
PowerShell search multiple files for a text string and replace with corresponding new text values from a list RRS feed

  • Question

  • Could use a hand with the following using PowerShell:

    Production environment and Test environment consists of: 
    Windows Server 2008 and 2012 with PowerShell.
    60+ individual files, each located inside 60+ individual folders inside a top level folder.
    No other applications can be installed or self contained .EXE files can be run on the servers for security reasons. PowerShell 3.0 or 4.0 however can be used for this task.

    Each file has a unique value which needs to be replaced with another unique value from a list.

    The list has two columns, one with the value to be searched for and the other with the replacement value.

    Example tab separated text list file:

    SearchFor ReplaceWith
    10.10.10.1 192.168.2.1
    10.10.10.2 192.168.2.2

    Goal: Batch replace multiple unique values with the other unique values with the least amount of code.

    Pseudo code:

    Begin script.

    Load file with list of values to search and replace on an array in memory

    Open first file to search into for reading.
    Find matching SearchFor value from first column in array.
    If match found, replace SearchFor value with corresponding ReplaceWith value from the array.
    Log results into file "results.txt" for later review.
    Recursively do this for each of the 60+ files inside the nested folders.
    End script.

    Expected results:


    Sample files to search:
    C:\Files\Folder1\File1.txt
    C:\Files\Folder2\File2.txt
    Etc...

    Sample log file:
    Begin log
    SearchFor001 in File1 was replaced with ReplaceWith001
    Searchfor02 in File2 was replaced with ReplaceWith002

    Etc...

    End log


    Much gratitude for any useful answers or pointers.

    Cheers.

    Wednesday, February 4, 2015 6:45 PM

Answers

All replies

  • Hi,

    Looks like an exam question and/or homework problem.

    Please post what you have so far and what your issues are. Do you have any specific questions?


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, February 4, 2015 6:58 PM
  • The following article may help get you started.

    Replace characters in a text file

    Wednesday, February 4, 2015 7:02 PM
  • What I have is a snipet from another article in another post on the Web which works for recursively searching and replacing "SearchFor" text value with "ReplaceWith" text value:

    Sample snipet:

    gci C:\Projects *.config -recurse | ForEach {
      (Get-Content $_ | ForEach {$_ -replace "old", "new"}) | Set-Content $_ 
    }

    Source: http://stackoverflow.com/questions/2837785/powershell-script-to-find-and-replace-for-all-files-with-a-specific-extension

    What I figured out with this snipet is: I would have to manually create 60 lines each containing the unique search pattern for each pair of values to search for and replace.

    My idea is to get a way to: Load the 'SearchFor' and 'ReplaceWith' in memory and recursively search and replace the 'SearchFor' and 'ReplaceWith' text value pairs accordingly and log the results for verification.

    Found the other snipet below which does a similar task. Once again the idea is to meld or integrate the below and above snipets into a more succinct process instead of making 60 lines of the same thing. In other words make it reusable

    I believe these two will do the job. Just need to figure out the right logic to integrate them with each other, ala nested loop or some other way?

    Once again any hints from the friendly script guru in the neighborhood would be appreciated.

    function Get-ReplacedText
    {
        [CmdletBinding()]
        Param
        (
            # Path containing the text file to be searched.
            $FilePath,
    
            # Path containing the patterns to be searched and replaced.
            $SearchPatternFilePath
        )
    
        # Patterns will be read in full for fast access.
        $patterns = Get-Content -Path $SearchPatternFilePath 
    
        # Use the StreamReader for efficiency.
        $reader = [System.IO.File]::OpenText($FilePath)
    
        # Open the file
        while(-not $reader.EndOfStream)
        {
            $line = $reader.ReadLine()
    
            foreach ($pattern in $patterns) {
    
                $search, $replacement = $pattern.Split()
    
                # Replace any searched text that exist with replacement.
                $line = $line -replace $search, $replacement
            }
    
            # Get the replaced line out of the pipeline.
            $line
        }
    
        #Close the file.
        $reader.Close()
    }

    Wednesday, February 4, 2015 9:41 PM
  • Yes this is similar hint one of the ones I found.

    Looking for a way to update multiple nested files with multiple unique 'SearchFor' and 'RepalceWith' value pairs but the logic to combine these thoughts\snipets in a simplified way eludes me.

    Much gratitude for your hint.

    Wednesday, February 4, 2015 10:03 PM
  • Here is a hint at how to approach this.

    $replacements=Import-Csv replacements.csv
    
    $text=Get-Content -raw
    
    
    $replacements |
        ForEach-Object{
            $text=$text -replace $_.pattern,$-.replacement
       }
    $file | Out-File <fixed file>
    


    ¯\_(ツ)_/¯

    Wednesday, February 4, 2015 10:41 PM
  • Here is a hint at how to approach this.

    $replacements=Import-Csv replacements.csv
    
    $text=Get-Content -raw
    
    
    $replacements |
        ForEach-Object{
            $text=$text -replace $_.pattern,$-.replacement
       }
    $file | Out-File <fixed file>


    ¯\_(ツ)_/¯

    Given the nature of the data being searched for and replaced, if you can read the whole file into memory at once I think you'd be better off using string replace() methods.  It's faster, and you don't have to worry about escaping any regex metacharacters in the search strings.

    replacements=Import-Csv replacements.csv
    
    $text=Get-Content -raw
    
    
    $replacements |
        ForEach-Object{
            $text=$text.Replace($_.pattern,$_.replacement)
       }
    $file | Out-File <fixed file>


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "


    Wednesday, February 4, 2015 11:32 PM
    Moderator
  • Apologies, I am trying to keep it super simple.

    Regex, metacharacters, etc = blank stare...maybe when i have 50 or 90K points under my belt i will know what that means...

    Thanks again for your hint.

    Thursday, February 5, 2015 1:20 AM
  • Apologies, I am trying to keep it super simple.

    Regex, metacharacters, etc = blank stare...maybe when i have 50 or 90K points under my belt i will know what that means...

    Thanks again for your hint.

    Then you need to run this, and read through it:

    Get-Help about_Regular_Expressions

    The -replace operator you're using in your script takes a regular expression as it's pattern argument.  Some characters in a regular expression have a special meaning (these are the "metacharacters"), and need to be escaped with a backslash if you want to match them literally.  One of these characters is the dot (.), and you appear to have some of those in the data you're getting ready to use for your patterns.  

    The string replace method does a literal, character-for-character match to the pattern match string.  None of the characters have an special meaning so you don't have to worry about whether they need to be escaped or not.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "


    Thursday, February 5, 2015 1:42 AM
    Moderator
  • The Replace-FileString.ps1 script I wrote a while back may also be of use.

    Windows IT Pro: Replacing Strings in Files Using PowerShell


    -- Bill Stewart [Bill_Stewart]

    Thursday, February 5, 2015 2:14 AM
    Moderator
  • Thanks for your hints to read and learn about regex, and for the script to replace strings on single text files.

    Every hint is valuable, much gratitude.

    Thursday, February 5, 2015 11:21 PM