Jump to content

How can I Find and Replace multiple strings in multiple files ?


Recommended Posts

Hello group,

I am new to AutoIt and have a LITTLE experience in VBscript. I am building an AutoIt application with the following goals:

1 - Ask user to supply some strings

2 - Search specific files and replace ANY and ALL of the found strings with the user-supplied strings.

I found and I tweaked Larry's solution to work with a set of files as defined in an Array.

Here is the code I have so far, which DOES work, but I am wondering if a kind Guru here could tell me if there is a more elegant/efficient/safe way to accomplish this task. I will ultimately have in the neighborhood of 30 strings to replace in 15 different files. Some files will have all 30 strings, other files will have only a subset of the strings.

;Define file set
Dim $arrFileSet[10], $filesCount
$arrFileSet[0] = "C:\Test\File0.bat"
$arrFileSet[1] = "C:\Test\File1.xml"
$arrFileSet[2] = "C:\Test\File2.ini"
$arrFileSet[3] = "C:\Test\File3.txt"
$arrFileSet[4] = "C:\Test\File4.txt"
$arrFileSet[5] = "C:\Test\File5.txt"
$arrFileSet[6] = "C:\Test\File6.txt"
$arrFileSet[7] = "C:\Test\File7.txt"
$arrFileSet[8] = "C:\Test\File8.txt"
$arrFileSet[9] = "C:\Test\File9.txt"
 
;Define user input variables
Dim $domain, $user, $pass, $share
$domain = InputBox("","Domain?")
$user = InputBox("","User?")
$pass = InputBox("","Pass?")
$share = InputBox("","Share?")
 
;Create array to store user input
Dim $arrUserInput[4]
$arrUserInput[0] = $domain
$arrUserInput[1] = $user
$arrUserInput[2] = $pass
$arrUserInput[3] = $share
 
;Create array to store to-be-replaced strings
Dim $arrStringsReplace[4], $stringToReplace, $stringCount
$arrStringsReplace[0] = "%domain%"
$arrStringsReplace[1] = "%user%"
$arrStringsReplace[2] = "%pass%"
$arrStringsReplace[3] = "%share%"
 
;Loop through files and strings
For $filesCount = 0 To 3
    $stringToReplace = FileRead($arrFileSet[$filesCount],FileGetSize($arrFileSet[$filesCount]))
  For $stringCount = 0 To 3
   $stringToReplace = StringReplace($stringToReplace, $arrStringsReplace[$stringCount], $arrUserInput[$stringCount])
   FileDelete($arrFileSet[$filesCount])
   FileWrite($arrFileSet[$filesCount],$StringToReplace)
  Next
Next

Thanks in advance!

Link to comment
Share on other sites

I don't know why you are using FileDelete. I would be inclined to use FileOpen with mode set to 2 = Write mode (erase previous contents), and then use FileWrite to replace the text, after all the replacements have been made to the text (string variable).

Edited by czardas
Link to comment
Share on other sites

I don't know why you are using FileDelete. I would be inclined to use FileOpen with mode set to 2 = Write mode (erase previous contents), and then use FileWrite to replace the text, after all the replacements have been made to the text (string variable).

I was using FileDelete because that is what I found in That said, I don't NEED to do it that way. So you are suggesting this instead?

FileOpen($arrFileSet[$filesCount], 2)
Edited by jsmcpn
Link to comment
Share on other sites

Correct. I'll be releasing a renaming example in the next couple of days, check back to the examples section once I've completed it.

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

There's also the command _ReplaceStringInFile that can do the same thing, it's basically just opening the file with a fileread, and then just finding all the occurences of the string to be replaced, and replaces it. Then writes the file back to the original file.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Preview:

Posted Image

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

There's also the command _ReplaceStringInFile that can do the same thing, it's basically just opening the file with a fileread, and then just finding all the occurences of the string to be replaced, and replaces it. Then writes the file back to the original file.

Excellent! I like that much better. I also added a line to back up each file.

#include <File.au3>
For $filesCount = 0 To 3
FileCopy($arrFileSet[$filesCount], $arrFileSet[$filesCount] & ".bak")
  For $stringsCount = 0 To 3
   _ReplaceStringInFile($arrFileSet[$filesCount],$arrStringsFind[$stringsCount],$arrBuildVars[$stringsCount])
  Next
Next
Edited by jsmcpn
Link to comment
Share on other sites

I'd think you would want your FileWrite() outside of the inner For/Next loop, so you're only executing it once per file, rather than after each variable replacement.

Something like:

#include <File.au3>
 
;Define and load file set
Local $arrFileSet
_FileReadToArray(@ScriptDir & "\files.txt", $arrFileSet)
 
;Define user input variables
Local $stringCount, $string[4] = ["Domain", "User", "Pass", "Share"]
;Define create arrays to store user input and to-be-replaced strings
Local $arrUserInput[4], $arrStringsReplace[4], $stringToReplace
For $x = 0 to 3
  $arrUserInput[$x] = InputBox("", $string[$x] & "?")
  $arrStringsReplace[$x] = "%" & $string[$x] & "%"
Next
 
;Loop through files and strings
For $filesCount = 1 To Ubound($arrFileSet) - 1
    $stringToReplace = FileRead($arrFileSet[$filesCount])
    For $stringCount = 0 To 3
      $stringToReplace = StringReplace($stringToReplace, $arrStringsReplace[$stringCount], $arrUserInput[$stringCount])
    Next
    FileMove($arrFileSet[$filesCount], $arrFileSet[$filesCount] & ".bak", 1)
    FileWrite($arrFileSet[$filesCount], $stringToReplace)
Next

I did a little more tinkering as well. You might find it useful to load your list of filenames from a text file as this example does. Then you can make changes to the list on-the-fly without recompiling your script.

PS - _ReplaceStringInFile() isn't very efficient for your particular needs, as you'll be opening, reading, rewriting, and closing each file 4 times (for each changed string) instead of just once with FileWrite().

Edited by Spiff59
Link to comment
Share on other sites

Thanks Spiff59, I'll experiment with your idea. In the meantime, can you help me with using a 2D array?

EDIT: Nevermind, I figured it out:

($arrFileSet[$filesCount],$arrStringsFindReplace[$stringCount][0],$arrStringsFindReplace[$stringCount][1])

OLD:

I was thinking it would be better to use a single 2D array for find/replace instead of two 1D arrays, but I must be misunderstanding 2D, because I get an error with the code below.

Array variable has incorrect number of subscripts or subscript dimension range exceeded.:

_ReplaceStringInFile($arrFileSet[$filesCount],$arrStringsFindReplace[$stringCount],$arrStringsFindReplace[1])

_ReplaceStringInFile($arrFileSet[$filesCount],^ ERROR

Dim $arrStringsFindReplace[4][2], $stringCount
$arrStringsFindReplace[0][0]  = "%varDomain%"
$arrStringsFindReplace[0][1]  = $varDomain
$arrStringsFindReplace[1][0]  = "%varUser%"
$arrStringsFindReplace[1][1]  = $varUser
$arrStringsFindReplace[2][0]  = "%varPass%"
$arrStringsFindReplace[2][1]  = $varPass
$arrStringsFindReplace[3][0]  = "%varShare%"
$arrStringsFindReplace[3][1]  = $varShare
 
For $filesCount = 0 To UBound($arrFileSet)-1
  FileCopy($arrFileSet[$filesCount], $arrFileSet[$filesCount] & ".bak")
    For $stringCount = 0 To UBound($arrStringsFindReplace)-1
      _ReplaceStringInFile($arrFileSet[$filesCount],$arrStringsFindReplace[$stringCount],$arrStringsFindReplace[1])
  Next
Next

Thanks again all!

Edited by jsmcpn
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...