Replace a middle string in .bat file using AutoHotKey without deleting file - autohotkey

I need to edit standalone.bat file using ahk script. I want to increase my heap size using ahk so below is line where i have to change heap in my bat file. Now i have trying to edit this using StringReplace and FileAppend but FileAppend keeps on appending string to the end
from
set "JAVA_OPTS=-Dprogram.name=%PROGNAME% -Xms64M -Xmx1426M %JAVA_OPTS%"
to
set "JAVA_OPTS=-Dprogram.name=%PROGNAME% -Xms64M -Xmx1426M %JAVA_OPTS%"xms000M
I am new to .ahk, i have tried this using some search
Loop, read, C:\standalone.bat
{
Line = %A_LoopReadLine%
replaceto = xms000M
IfInString, Line, Xmx1426M
, Line, replaceto, %Line%, %replaceto%
FileAppend, %replaceto%`n
StringReplace FileAppend
}
Is it possible to replace middle string using ahk. thanks

Fileappend will always append to the end of a file. Why do you want to prevent a temporary deletion of your batch file?
Typically, in ahk, you'd do it like this..
batFile = C:\standalone.bat
output := ""
Loop, read, %batFile%
{
Line = %A_LoopReadLine%
IfInString, Line, Xmx1426M
{
StringReplace, Line, Line, Xmx1426M, xms000M
; note: Regular Expressions can be used like Line := regExReplace(Line, "...", "...")
}
output .= Line . "`n" ; note: this is the same as if to say output = %output%%Line%`n or output := output . line "`n"
}
FileDelete, %batFile%
FileAppend, %output%, %batFile%
This will delete your file for some little milliseconds, just to recreate it with the new content afterwards. I don't really see any difference to editing it without deletion, because in either way, you'll need write access to the file.
Some words about your code sample:
IfInString, Line, Xmx1426M
, Line, replaceto, %Line%, %replaceto%
will be interpreted as
"If the string 'Line' contains 'Xmx1426M , Line, replaceto, %Line%, %replaceto%'"
which does not make any greater sense.
FileAppend, %replaceto%\n is lacking a destination file.
StringReplace FileAppend: these are two commands without any further parameters. You must never put two non-function-commands in the same line!

Related

Looking up data from a file, and storing them as variables

I'm new to autohotkey and I can't figure out how to solve this. Any help is appreciated.
I have list.txt which includes ids and names like this:
list.txt:
123124 - whatever
834019 - sometext
3980 - afjalkfj
I need a function that can do the following
lookup(id, name){
** The function here should lookup for the id inserted
then save ONLY the data related to it in variable x (not the full line)
}
Example
lookup(834019, x)
%x% = sometext
Please help me to do this. Thanks!
What you need in this case are
FileRead to read the file's contents into a variable.
A parsing loop to parse the text of each line.
The StrSplit() function to split the text of each line into an
array of Substrings using the specified Delimiters.
The second parameter (name) is redundant in this case. You can omit it:
x := lookup(834019)
MsgBox, % x
MsgBox, % lookup(3980)
lookup(id) {
FileRead, Contents, list.txt ; read the file's contents into the variable "Contents"
if not ErrorLevel ; Successfully loaded.
{
Loop, parse, Contents, `n, `r ; parse the text of each line
{
word_array1 := StrSplit(A_LoopField," - ").1 ; store the first substring into the variable "word_array1"
word_array1 := Trim(word_array1, " `t") ; trim spaces and tabs in this variable
If (word_array1 = id)
{
name := StrSplit(A_LoopField," - ").2
name := Trim(name, " `t")
return name
}
}
Contents := "" ; Free the memory.
}
else
MsgBox, A problem has been encountered while loading the File Contents
}

Split String in Array into an array autohotkey

Trying to read a CSV file in Auto Hot Key and line by line split the line by "," to pull out the last two columns of each line. Currently just trying to get the string to split into an array. I can print each line with the line
MsgBox, A_LoopReadLine but cannot split the string inside of the variable.
Have tried StringSplit and StrSplit but I am sure the syntax is incorrect.
MyArray := Object()
Loop, read, %fileop%
{
MyArray.Insert(A_LoopReadLine) ; Append this line to the array.
index := 1
MsgBox, %A_LoopReadLine%
;MyArray.
;MsgBox, % StrSplit(A_LoopReadLine ,",")
}
Loop % MyArray.Length()
MsgBox % StrSplit(MyArray[A_Index],",")
Trying to read a CSV file in Auto Hot Key and line by line split the
line by "," to pull out the last two columns of each line.
MyArray := Object()
Loop, Read, %fileop%
MyArray[A_Index]:=StrSplit(A_LoopReadLine,",")
This will store your csv file in MyArray[row][column] format. E.g to access second item in fifth row: MyArray[5][2]
for k,v in MyArray
v.RemoveAt(1,v.Length()-2)
Above will remove all but last two items from each row.
Documentation:
https://autohotkey.com/docs/commands/For.htm
https://autohotkey.com/docs/objects/Object.htm#RemoveAt_v1121+
https://autohotkey.com/docs/objects/Object.htm#Length
Edit:
And to as to why your code did not work. It kinda did.
The thing is that StrSplit() returns object, array so with below line you were trying to display object in MsgBox, this is not allowed.
MsgBox % StrSplit(MyArray[A_Index],",")
This for example would work:
MsgBox % StrSplit(MyArray[A_Index],",")[1]

How to send line by line data from a .txt file using autohotkey?

Dear friends I am trying to send data from a .txt file to some another file by using Loop (read file contents) command in autohotkey. But it is not sending it line by line i.e. it is sending it continuously. As I made a script which is as follows-
F1::
Loop, read, C:\Data.txt
{
Loop, parse, A_LoopReadLine, %A_Tab%
{
Send %A_LoopField%
}
}
In the above example I made F1 a hotkey.
There is a data.txt file in my D: drive. Now I want that when I press F1 key it should send only one line at a time from data.txt file. When I again press F1 key, it should send next line from that file and so on. But it is not doing so. It is sending the data from data.txt file on the trot (continuously) till the end of the file.
Friends kindly suggest me any solution of this problem.
You can load the file-data outside the hotkey, then loop through it inside the hotkey and get the appropriate line. I'm not sure how fast this would be with huge files though.
; Uncomment this to load data from a file
;FileRead, fileData, C:\data.txt
; This is only for testing
fileData =
(LTrim
Line one
Line two
Line three
)
; Init lineIndex to 1
lineIndex := 1
F1::
Loop, Parse, fileData, `n
{
; A_Index holds the current loop-itteration
if (A_Index == lineIndex) {
SendInput, %A_LoopField%
; Increment lineIndex
lineIndex++
break
}
}
return
Esc::ExitApp

FileAppend data loss in a loop

In a loop, I use FileAppend to add text to a file. In every iteration of the loop, the data is accumulated in a variable and FileAppend is called every n iterations of the loop to save the data. Very occasionally, after a FileAppend call, the data accumulated in the variable during the next iteration is lost. As it is very intermittent, I could not reproduce this behavior. It seems like if, in some situation, the script would need a delay after FileAppend. Is this a known issue? I've search AHK forums and this site without report of such issue.
Here is a piece of code where this happens:
Loop, %intMax% ; for each record in the collection
{
if !Mod(A_Index, intProgressIterations)
; update the progress bar and save the data every intProgressIterations
; (when intProgressIterations / A_Index = 0)
{
ProgressUpdate(A_index, intMax, strProgressText)
; update progress bar only every %intProgressIterations% iterations
FileAppend, %strData%, %strFilePath%
strData := ""
; save the data accumulated in strData and empty it
}
strData := strData . BuildData(objCollection[A_Index])
; build the data for this record and add it to strData
}
More precisely, it is the content of one (or more) iteration of the line strData := strData . BuildData(objCollection[A_Index]) that is lost.
Could be any number of things. The file could be locked, there could be an error in your BuildData function that causes it not to produce data.
I'd recommend checking the last modified date before and after you append the data.
If it's the same, you can either try again and/or notify the user.
As to your question about the delay, it shouldn't need it, the script does not continue to the next line of code until it finishes writing to the file.
Following findings about file locking, this code with error management will be safer:
Loop, %intMax% ; for each record in the collection
{
if !Mod(A_Index, intProgressIterations)
; update the progress bar and save the data every intProgressIterations
; (when intProgressIterations / A_Index = 0)
{
ProgressUpdate(A_index, intMax, strProgressText)
; update progress bar only every %intProgressIterations% iterations
Loop
{
FileAppend, %strData%, %strFilePath%
; save the data accumulated in strData and empty it after the loop
if ErrorLevel
Sleep, 20
}
until !ErrorLevel or (A_Index > 50) ; after 1 second (20ms x 50), we have a problem
if (ErrorLevel)
strError := strError . "Error writing line " . A_Index . " Error: #" . A_LastError . "`n"
strData := ""
}
strData := strData . BuildData(objCollection[A_Index])
; build the data for this record and add it to strData
}
As an added point to this issue (for future searches)... I found that trying to FileAppend within a loop when the output file is on Dropbox, will also cause data loss.
Dropbox will detect updates to the file during the early cycles of the loop, and then lock it while it sends the updated (updating) file to the Dropbox servers. I've tracked data loss in a text file as short as 150 lines of text.
The solution I used was to create a temp output file outside of the Dropbox-monitored main folder, and write to it instead. When the loop is complete, copy the temp file back to Dropbox, and then delete the temp file.
Here's an partial code example of how I did the switch with a completed temp file, after the loop had finished:
; Copy the Daily Scrub temp file to var holding the filepath to todo.txt, then delete the Daily Scrub temp file
FileCopy, C:\temp-dailyscrub.txt, %todoFilePathParse%, 1
FileDelete, C:\temp-dailyscrub.txt

AHK - stdout to variable working, but unable to use a variable inside comspec

I have stdout feeding to a variable when I use literal filepaths in my comspec line, but why can I not use a variable in place of the filename I want to be analyzed?
Note that mediainfo already (successfully) uses the % symbol in its own arguments. So how do I make comspec treat %LongPath% as a real variable?
I already tried adding an extra pair of quotes around %Longpath% as well, but no luck.
Loop %0%
{
Path := %A_Index%
Loop %Path%, 1
LongPath = %A_LoopFileLongPath%
SplitPath LongPath, OutFileName, OutDir, OutExtension, OutNameNoExt, OutDrive
objShell := ComObjCreate("WScript.Shell")
objExec := objShell.Exec(comspec " /c C:\MediaInfo.exe --Inform=Video;%FrameRate% %LongPath%")
framerate := ""
while, !objExec.StdOut.AtEndOfStream
framerate := objExec.StdOut.ReadAll()
msgbox %framerate%
}
Thanks for some expertise.
The key was the enclose the appname and arguments in quotes, (and make sure to leave an extra space before the last quote) and then not to include your final variable in the quotes.