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