Find Replace

From AutoIt Wiki
Jump to navigation Jump to search

Initial post: 21-Jan-2005

Back to Samples

Purpose:

Convert one string to another in a file which is dragged onto the EXE or that is passed by commandline.

Notes:

This solution employs more of a "brute force" approach than one using FileRead("filename", FileGetSize("filename")) .. but has the advantage of being able to handle large files far more efficiently!

Illustrates:

  • Text file processing, including output to a LOG file.
  • Commandline processing.
  • A trick for testing before compile-and-deploy.
  • Elementary usage of a UDF.
  • Hungarian notation and proper indentation.
  • How to get around without "goto".
  • Various methods of AU3 script deployment.
 ; ----------------------------------------------------------------------------
 ;
 ; AutoIt Version: 3.0.103.xxx
 ; Language:       English
 ; Author:         Trids 
 ;
 ;   SCRIPT FUNCTION:
 ;   =================
 ;   an applet to convert a particular string to another in a file
 ;   which is dragged onto the EXE or that is passed by commandline
 ;
 ;   FEATURES
 ;   =================
 ;   + Can handle huge files (based on a request from a DBA 
 ;     to edit her test-scripts of around 200Mb).
 ;   + Prompts the user for ..
 ;       o Search String.
 ;       o Replace String 
 ;         (defaults with Search String for easy modification).
 ;       o Output file name 
 ;         (defaults to Input filename with ".DAT" appendix).
 ;
 ;   REQUIREMENTS
 ;   =================
 ;   + Commandline parameters
 ;       o Reference to an input file which has strings to replace.
 ;   + There may be scope in the future to make adjustments to allow
 ;     the utility to be run in a scheduled manner <-- in which case,
 ;     we would replace the current user-prompts with further
 ;     commandline parameters.
 ;
 ;   RESULTS
 ;   =================
 ;   - Output file with edits applied.
 ;   - Errors and other events are reported to a *.LOG file 
 ;     based on the same name and path as the script.
 ;
 ;   DEPLOYMENT
 ;   =================
 ;   - Since the applet expects to receive an input file reference from 
 ;     the commandline, there are several ways to launch the utility.
 ;       o Drag-and-Drop: just drag the input file onto the icon 
 ;         of the compiled EXE, or onto a shortcut to the EXE.
 ;       o SendTo: create a shortcut to the EXE, and place this shortcut in 
 ;         the "SendTo" folder. This will allow the user to rightclick on 
 ;         an input file and follow the "Send To" popup menu item to pass 
 ;         the file to the EXE.
 ;   
 ; ----------------------------------------------------------------------------
 Global $gsFileLOG = StringTrimRight(@ScriptFullPath,3) & "LOG"
 
     _WriteLog(@LF & @SCRIPTNAME & " .. starting")
     
 ; ----------------------------------------------------------------------------
 ; Confirm that a commandline reference to a valid input file was passed
 ; ----------------------------------------------------------------------------
     
     $sMsg = ""
     If @COMPILED Then
         ;PROD --> Check for commandline parameter and validate
         ;PROD --> Check for commandline parameter and validate
         ;PROD --> Check for commandline parameter and validate
         If $CmdLine[0] = 0 Then
             $sMsg = "*** ERROR *** No commandline reference was provided, to a TXT file to reformat."
             $sFile_IN = ""
         Else
             $sFile_IN = $CmdLine[1]
         Endif
         If FileExists($sFile_IN) Then
             ;cool
         Else
             $sMsg = "*** ERROR *** The input file to reformat does not exist: """ & $sFile_IN & """"
         Endif
     Else
         ;TEST --> provide default for testing
         ;TEST --> provide default for testing
         ;TEST --> provide default for testing
         $sFile_IN = "P:\bigfile.out"
         MsgBox(4096,"Debug mode", "File to reformat = """ & $sFile_IN & """")
     Endif     
 
 ; ----------------------------------------------------------------------------
 ; Reformat and write
 ; ----------------------------------------------------------------------------
     While 1     ;<-- dummy loop to avoid goto ;o)
         ;check for error in dragged filename
         If $sMsg <> "" Then 
             _WriteLog($sMsg)
             ExitLoop
         Endif
         
         $sFile_IN = FileGetLongName($sFile_IN)
         
         ;get and check the search string
         $sStr_Find = InputBox(@ScriptName, $sFile_IN & @LF & @LF & ".. FIND this:", "", "", 430, 150)
         If $sStr_Find = "" Then
             _WriteLog("*** ERROR *** Search string must not be empty.")
             ExitLoop
         Else
             _WriteLog("FIND string = """ & $sStr_Find & """")
         Endif
             
         ;get and check the replacement string
         $sStr_Replace = InputBox(@ScriptName, $sFile_IN & @LF & @LF & ".. REPLACE with:", $sStr_Find, "", 430, 150)
         If $sStr_Replace = "" Then
             _WriteLog("*** ERROR *** Replacement string must not be empty.")
             ExitLoop
         Else
             _WriteLog("REPLACE string = """ & $sStr_Replace & """")
         Endif
         
         ;get and check the output file name
         $sFile_OUT = $sFile_IN & ".dat"
         $sFile_OUT = InputBox(@ScriptName, "Output filename", $sFile_OUT, "", 430, 150)
         If $sFile_OUT = "" Then
             _WriteLog("*** ERROR *** Output filename must be specified.")
             ExitLoop
         Else
             _WriteLog("Output file = """ & $sFile_OUT & """")
         Endif
         
         ;apply the edits line by line - faster than manipulating a single string!
         $nFile_IN = FileOpen($sFile_IN,0)
         $nFile_OUT = FileOpen($sFile_OUT,2)
         If $nFile_IN = -1 Or $nFile_OUT = -1 Then 
             _WriteLog("*** ERROR **** problem opening files: (IN/OUT) = (" & $nFile_IN & "/" & $nFile_OUT & ")") 
         Else
             ;process the file
             $nHits = 0
             While 1
                 $sData = FileReadLine($nFile_IN)
                 If @ERROR = -1 Then ExitLoop
                 $sX = StringReplace($sData, $sStr_Find, $sStr_Replace,0,0)
                 If @EXTENDED <> 0 Then $nHits = $nHits + 1
                 FileWriteLine($nFile_OUT, $sX)
             Wend
             FileClose($nFile_OUT)
             FileClose($nFile_IN)        
             _WriteLog("File created: """ & $sFile_OUT & """")
             _WriteLog("Lines affected: " & $nHits )
             If $nHits Then
                 ;nothing to mention
             Else
                 MsgBox (4096 + 48, @ScriptName, "No replacements were made!")
                 _WriteLog("+++ WARNING +++ No replacements were made!")
             Endif
         Endif
         
         ;Do this all once only
         ExitLoop
     Wend
 
     _WriteLog(@SCRIPTNAME & " .. ending" & @LF & @LF)
 
 
 Func _WriteLog($psText)
     FileWriteLine($gsFileLOG , @YEAR & "-" & @MON & "-" & @MDAY & " (" & @HOUR & ":" & @MIN & ":" & @SEC & "): " & $psText)
 EndFunc