kiffab Posted July 11, 2011 Share Posted July 11, 2011 Hi there I am looking to read a file backwards into an array then search for a particular string. When the string is found, I want to output it (at least when testing). I only want to output the first occurrence. I've searched around this forum, combining code from different posts but it outputs every occurence of the string. How would I change this to do as stated above? Thanks! #include <file.au3> $File_Name = "mylog.log" $Find = "hello" Dim $Records If ReadFileBackwards("mylog.log", $Records) Then For $x = $Records[0] To 1 Step - 1 if StringInStr($Records[$x], $Find) Then Msgbox(0,'Record:' & $x, $Records[$x]) Next Else EndIf Exit Func ReadFileBackwards($SFilepath, ByRef $AArray) Local $HFile $HFile = FileOpen($SFilepath, 0) If $HFile = -1 Then SetError(1) Return 0 EndIf $AArray = StringSplit( StringStripCR( FileRead($HFile, _ FileGetSize($SFilepath))), @LF) FileClose($HFile) Return 1 EndFunc Link to comment Share on other sites More sharing options...
kiffab Posted July 11, 2011 Author Share Posted July 11, 2011 Hmm... is ubound the way to go here? for $x = $Records[0] to Ubound ($Records) -1 Link to comment Share on other sites More sharing options...
jaberwacky Posted July 11, 2011 Share Posted July 11, 2011 Can you post mylog.log so that we can run the script under similar conditions? Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
Developers Jos Posted July 11, 2011 Developers Share Posted July 11, 2011 Something like this? #include <file.au3> $File_Name = "mylog.log" $Find = "hello" Global $Records _FileReadToArray("mylog.log",$Records) For $x = $Records[0] To 1 Step -1 If StringInStr($Records[$x], $Find) Then MsgBox(0, 'Record:' & $x, $Records[$x]) ExitLoop EndIf Next SciTE4AutoIt3 Full installer Download page  - Beta files    Read before posting   How to post scriptsource   Forum etiquette Forum Rules  Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
kiffab Posted July 11, 2011 Author Share Posted July 11, 2011 (edited) That works Jos. Thank you! Basically what I'm trying to do is find a string, then find another string and determine which one is the latest entry in the log file. From that I will be able to set the status of a variable Edited July 11, 2011 by kiffab Link to comment Share on other sites More sharing options...
Developers Jos Posted July 11, 2011 Developers Share Posted July 11, 2011 That works Jos. Thank you! Basically what I'm trying to do is find a string, then find another string and determine which one is the latest entry in the log file. From that I will be able to set the status of a variable Should be easy ... add the tests after the Next for what you want to test for: #include <file.au3> $File_Name = "mylog.log" $Find1 = "hello" $Find2 = "goodbye" Global $Records, $Found1=False, $Found2=False _FileReadToArray("mylog.log",$Records) For $x = $Records[0] To 1 Step -1 If StringInStr($Records[$x], $Find1) Then $Found1 = $x If StringInStr($Records[$x], $Find2) Then $Found2 = $x If $Found1 and $Found2 then ExitLoop Next SciTE4AutoIt3 Full installer Download page  - Beta files    Read before posting   How to post scriptsource   Forum etiquette Forum Rules  Live for the present, Dream of the future, Learn from the past. Link to comment Share on other sites More sharing options...
kiffab Posted July 11, 2011 Author Share Posted July 11, 2011 Thanks Jos. I had done this using variables x and y in 2 separate for loops but this seems more efficient Appreciate your help! Should be easy ... add the tests after the Next for what you want to test for: #include <file.au3> $File_Name = "mylog.log" $Find1 = "hello" $Find2 = "goodbye" Global $Records, $Found1=False, $Found2=False _FileReadToArray("mylog.log",$Records) For $x = $Records[0] To 1 Step -1 If StringInStr($Records[$x], $Find1) Then $Found1 = $x If StringInStr($Records[$x], $Find2) Then $Found2 = $x If $Found1 and $Found2 then ExitLoop Next Link to comment Share on other sites More sharing options...
kiffab Posted July 12, 2011 Author Share Posted July 12, 2011 Jos, I have created a GUI and included the function. If I call it outside the while loop, it works. That only lets me read the log once. I want to read it repeatedly, say every 1 minute. I tried using sleep command and placing it in the while loop. Also tried activating it by pressing the start button but no joy. Where am I going wrong? Thanks. expandcollapse popup#include <file.au3> #include <GUIConstantsEx.au3> Global $logFile = @scriptdir & "/mylog.log" $find1= "server1on" $find2 = "server1off" $status = "" Func Test() Global $Records, $Found1=False, $Found2=False _FileReadToArray($logFile,$Records) For $x = $Records[0] To 1 Step -1 If StringInStr($Records[$x], $find1) Then $Found1 = $x If StringInStr($Records[$x], $find2) Then $Found2 = $x If $Found1 and $Found2 then ExitLoop Next If $Found1 > $Found2 Then $status = "ON" EndFunc $GUI = GUICreate("App", 400, 400) GUICtrlCreatePic('bg.bmp', 0, 0, 400, 400) GuiCtrlSetState(-1,$GUI_DISABLE) GUISetFont(9, 1, 3, "verdana") GUISetState() GUICtrlCreateLabel("server1", 10, 10, 80, 30) GuiCtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlCreateLabel($status, 100, 10, 80, 30) GuiCtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) $start = GUICtrlCreateButton("Start",10, 160, 80, 30) While 1 $msg = GUIGetMsg() Switch $Msg Case $GUI_EVENT_CLOSE Exit Case $start Test() EndSwitch WEnd ;GUIDelete() ; not sure if this is needed Exit Link to comment Share on other sites More sharing options...
jchd Posted July 12, 2011 Share Posted July 12, 2011 _ArraySearch with Partial = 1 and Forward = 0 should be your one-liner for this. This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
kiffab Posted July 12, 2011 Author Share Posted July 12, 2011 In the function or within the while loop? Thx Link to comment Share on other sites More sharing options...
AdmiralAlkex Posted July 12, 2011 Share Posted July 12, 2011 In the function or within the while loop?ThxInstead of the loop .Some of my scripts: ShiftER, Codec-Control, Resolution switcher for HTC ShiftSome of my UDFs: SDL UDF, SetDefaultDllDirectories, Converting GDI+ Bitmap/Image to SDL Surface Link to comment Share on other sites More sharing options...
kiffab Posted July 12, 2011 Author Share Posted July 12, 2011 Instead of the loop Sorry if I'm being stupid here... how would this work? Would I not need a for loop or something so the log file would be read every x seconds/minutes? Appreciate the help you guys have given me Link to comment Share on other sites More sharing options...
Malkey Posted July 13, 2011 Share Posted July 13, 2011 (edited) Sorry if I'm being stupid here... how would this work? Would I not need a for loop or something so the log file would be read every x seconds/minutes? .... Change AdlibRegister("MyAdlib", 6000) to AdlibRegister("MyAdlib", 60000) for every 60 seconds. A test "mylog.log" file used. Line 1 Hello 2 Line 3 Hello 4 Line 5 Hello 6 Line 7 An example. expandcollapse popup#include <file.au3> #include <Array.au3> HotKeySet("{ESC}", "Terminate") AdlibRegister("MyAdlib", 6000) ; 6000 millsec = 6 seconds Global $sFile_Name = @ScriptDir & "\mylog.log" Global $sFind1 = "hello" Global $sFind2 = "line" ;Initial MsgBox MsgBox(0, "Press ESC to Exit", 'Last "' & $sFind1 & '" is in the line "' & _FindInLog($sFile_Name, $sFind1) & '".' & @LF & _ 'Last "' & $sFind2 & '" is in the line "' & _FindInLogA($sFile_Name, $sFind2) & '".', 4) While 1 Sleep(50) WEnd Func MyAdlib() MsgBox(0, "Press ESC to Exit", 'Last "' & $sFind1 & '" is in the line "' & _FindInLog($sFile_Name, $sFind1) & '".' & @LF & _ 'Last "' & $sFind2 & '" is in the line "' & _FindInLogA($sFile_Name, $sFind2) & '".', 4) EndFunc ;==>MyAdlib ; _FindInLog() returns the line that $Find1 is found in. Func _FindInLog($File_Name, $Find) Local $Records _FileReadToArray($File_Name, $Records) #cs For $x = $Records[0] To 1 Step -1 If StringInStr($Records[$x], $Find1) Then $Found1 = $x If StringInStr($Records[$x], $Find2) Then $Found2 = $x If $Found1 And $Found2 Then ExitLoop Next #ce Local $iIndex = _ArraySearch($Records, $Find, 0, 0, 0, 1, 0) Return $Records[$iIndex] EndFunc ;==>_FindInLogA ;or ; _FindInLogA() returns the line that $Find1 is found in. Func _FindInLogA($File_Name, $Find) Return StringRegExpReplace(FileRead($File_Name), "(?mis)^.*([^\v]*" & $Find & "[^\v]*).*", "\1") EndFunc ;==>_FindInLog Func Terminate() AdlibUnRegister("MyAdlib") Exit 0 EndFunc ;==>Terminate Edit: Changed RegExp from "(?is)^.*\v([^\v]*" & $Find & "[^\v]*).*" to match first line. Edit2: Changed RegExp from "(?is)^.*\v|\A([^\v]*" & $Find & "[^\v]*).*" to match first line. Edited July 13, 2011 by Malkey Link to comment Share on other sites More sharing options...
kiffab Posted July 13, 2011 Author Share Posted July 13, 2011 Thanks for your input Malkey. I was working on this last night and almost have it working as I want. My only problem is the X button in the top right corner won't work. I tried adding the lines: Case $msg = $GUI_EVENT_CLOSE ExitLoop but I've had to comment these out as the application closes immediately when they are present. My Exit button works fine but I'd like the X to work too! What am I missing? AdlibUnregister? Thanks again! expandcollapse popup#include <Array.au3> #include <file.au3> #include <GUIConstantsEx.au3> $find1 = "on" $find2 = "off" Global $logFile = @scriptdir & "/mylog.log" Global $Records $GUI = GUICreate("App", 300, 400) ;GUICtrlCreatePic('bg.bmp', 0, 0, 300, 400) ;set the background image GuiCtrlSetState(-1,$GUI_DISABLE) ;disable gui GUISetFont(12, 600, 1, "verdana") GUICtrlCreateLabel("Server 1", 10, 30, 100, 40) GuiCtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) $server1status = GUICtrlCreateLabel("Default", 10, 100, 80, 30) GuiCtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) $Start = GUICtrlCreateButton("Start", 20, 350, 80, 40) $Exit = GUICtrlCreateButton("Exit", 130, 350, 80, 40) Func Server1() _FileReadToArray($logFile,$Records) $iIndex1 = _ArraySearch($Records, $find1, 0, 0, 0, 1, 0) $iIndex2 = _ArraySearch($Records, $find2, 0, 0, 0, 1, 0) If $iIndex1 > $iIndex2 Then GUICtrlSetData($server1status, "On") Else GUICtrlSetData($server1status, "Off") EndIf EndFunc GUISetState() while 1 $msg = GUIGetMsg() Switch $msg case $Exit Exit case $start AdlibRegister("server1",10000) ;Case $msg = $GUI_EVENT_CLOSE ; ExitLoop EndSwitch WEnd GUIDelete() Exit Link to comment Share on other sites More sharing options...
Malkey Posted July 13, 2011 Share Posted July 13, 2011 .... I tried adding the lines: Case $msg = $GUI_EVENT_CLOSE ExitLoop .... That Case statement is used in in a Select ... EndSelect routine. Use Case $GUI_EVENT_CLOSE ExitLoop For a Switch....EndSwitch routine. Link to comment Share on other sites More sharing options...
kiffab Posted July 13, 2011 Author Share Posted July 13, 2011 That Case statement is used in in a Select ... EndSelect routine. Use Case $GUI_EVENT_CLOSE ExitLoop For a Switch....EndSwitch routine. Fantastic. Thank you. I knew it was something silly Basic logic is pretty much there. The only other thing I've noticed is that if you click "Start", it waits 10 seconds, then another 10 seconds before updating the status (20 secondS). I've cut this down to 10 seconds by calling the function before the AdlibRegister: case $start server1() AdlibRegister("server1",10000) Is it possible to update the status as soon as start is pressed? i.e. press start - change status to what it should be then 10 seconds later read file again and repeat? Cheers Link to comment Share on other sites More sharing options...
Malkey Posted July 13, 2011 Share Posted July 13, 2011 I have been playing with your script. It appears to be working fine. expandcollapse popup#include <Array.au3> #include <file.au3> #include <GUIConstantsEx.au3> Global $find1 = "on" Global $find2 = "off" Global $logFile = @ScriptDir & "/mylog.log" Global $Records Local $msg Local $GUI = GUICreate("App", 300, 400) GUISetFont(12, 600, 1, "verdana") ;GUICtrlCreatePic('bg.bmp', 0, 0, 300, 400) ;set the background image ;GUICtrlSetState(-1, $GUI_DISABLE) ; disable Pic control. GUICtrlCreateLabel("Server 1", 10, 30, 100, 40) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) Local $server1status = GUICtrlCreateLabel("Default", 10, 100, 80, 30) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) Local $Start = GUICtrlCreateButton("Start Server Check", 20, 350, 130, 20) GUICtrlSetFont(-1, 8, 600) Local $Exit = GUICtrlCreateButton("Stop Server Check", 155, 350, 130, 20) GUICtrlSetFont(-1, 8, 600) GUISetState() While 1 $msg = GUIGetMsg() Switch $msg Case -3 ; $GUI_EVENT_CLOSE = -3, as declared in #include <GUIConstantsEx.au3>. ExitLoop Case $Start Server1() AdlibRegister("server1", 10000) Case $Exit GUICtrlSetData($server1status, "Default") AdlibUnRegister("server1") EndSwitch WEnd AdlibUnRegister("server1") Func Server1() _FileReadToArray($logFile, $Records) Local $iIndex1 = _ArraySearch($Records, $find1, 0, 0, 0, 1, 0) Local $iIndex2 = _ArraySearch($Records, $find2, 0, 0, 0, 1, 0) ConsoleWrite("if " & $iIndex1 & " > " & $iIndex2 & ' then "on"' & @LF) ; Testing purposes only. If $iIndex1 > $iIndex2 Then GUICtrlSetData($server1status, "On") Else GUICtrlSetData($server1status, "Off") EndIf EndFunc ;==>Server1 Link to comment Share on other sites More sharing options...
kiffab Posted July 13, 2011 Author Share Posted July 13, 2011 I have been playing with your script. It appears to be working fine.Thanks Malkey. I've changed this slightly to use images which should update depending on the status. I've noticed they flicker when you click start (but remain at default setting) then after 10 seconds they will change to the correct image.Not sure why the image doesn't change as soon as start is clicked. Cheers. Link to comment Share on other sites More sharing options...
kiffab Posted July 13, 2011 Author Share Posted July 13, 2011 Thanks Malkey. I've changed this slightly to use images which should update depending on the status. I've noticed they flicker when you click start (but remain at default setting) then after 10 seconds they will change to the correct image.Not sure why the image doesn't change as soon as start is clicked. Cheers.Calling the function twice when start is clicked seems to fix this. Not sure if that's bad practice or not, but it works. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now