Find Replace
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