kiffab Posted July 11, 2011 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
kiffab Posted July 11, 2011 Author Posted July 11, 2011 Hmm... is ubound the way to go here? for $x = $Records[0] to Ubound ($Records) -1
jaberwacky Posted July 11, 2011 Posted July 11, 2011 Can you post mylog.log so that we can run the script under similar conditions? Helpful Posts and Websites: AutoIt Wiki | Can't find what you're looking for on the Forum? My scripts: Guiscape | Baroque AU3 Code Formatter | MouseHoverCalltips | SciTe Customization GUI | ActiveWindowTrack Toy | Monitor Configuration UDF
Developers Jos Posted July 11, 2011 Developers 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.
kiffab Posted July 11, 2011 Author 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
Developers Jos Posted July 11, 2011 Developers 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.
kiffab Posted July 11, 2011 Author 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
kiffab Posted July 12, 2011 Author 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
jchd Posted July 12, 2011 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)
kiffab Posted July 12, 2011 Author Posted July 12, 2011 In the function or within the while loop? Thx
AdmiralAlkex Posted July 12, 2011 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
kiffab Posted July 12, 2011 Author 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
Malkey Posted July 13, 2011 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
kiffab Posted July 13, 2011 Author 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
Malkey Posted July 13, 2011 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.
kiffab Posted July 13, 2011 Author 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
Malkey Posted July 13, 2011 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
kiffab Posted July 13, 2011 Author 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.
kiffab Posted July 13, 2011 Author 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.
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