Mellon Posted March 16, 2011 Posted March 16, 2011 (edited) I might be missing something obvious here and if I am forgive me. However, I cannot figure out why this script isn't working the way I want it to work. I have a text file I need to extract particular records from. While there is a ton of records in it the ones I need look like this: [++b8cc8293-b1d1-11d6-ba8b-f575a629e04c++] Name = 005 Type = Mark CreateTime = 2002-08-18 02:09:42Z Hidden = FALSE Locked = FALSE Desc = Color = 0x000000 LatLon = 58 24.92999 N 154 00.47400 W BmpIdx = 0 ArrivalCircleRadius = 0.050 nm NameOffset = -11,10 DescOffset = -15,20 ShowName = TRUE ShowDescription = FALSE RangeCircleColor = 0xff0000 RangeCircleDisplay Count = 0 RangeCirclePen Width = 1 BoundaryCircleOffLimits = None RangeCircleRadius = 0.500 nm RangeCircleBindToArrivalCircle = FALSE MarkRenamed = FALSE ExistsOutsideCollection = FALSE PlanningLegSOG = 0.5 kts NameDisplayMoved = FALSE TDChain1 = TDChain2 = Once I find Type = Mark the data I need is six lines down, the latlon field. Since this was meant to be quick and dirty I dashed off this: $w=0 $WhattoOpen=FileOpen("C:\stpete\Export.Txt",0) $WhattoWriteto=fileopen("C:\stpete\NobeltechMark.psv",1) While 1 $Checktheline=FileReadLine($WhattoOpen) ; read a line from the file $W = $W+1 $IsitaMark=StringInStr($Checktheline,"Type = Mark") ;find out if it is a mark record If $IsitaMark <> 0 Then $Thisisthelatlon=FileReadLine($whattoopen,$w+6) filewrite($WhattoWriteto,$Thisisthelatlon & @CRLF) $isitamark=0 endif WEnd When I look at the resulting text file this is what I see: LatLon = 46 56.18280 N 124 26.64430 W Type = Mark Type = Mark "Type = Mark" until the end of the file. The first time Type = Mark is found I get what I want. However, every other time it does not appear to add 6 to the value of $W. I cannot figure out why this isn't working. Edited March 16, 2011 by Mellon
GEOSoft Posted March 16, 2011 Posted March 16, 2011 For starters you don't need to use the first FileOpen(). FileRead() will take care of that. Based on the info you gave, I'm not sure if this is the results you are after or not but give it a try. #include<array.au3>;; Used for displaying the array only. $sStr = FileRead(C:\stpete\Export.Txt) $aLatLonng = StringRegExp($sStr, "(?i)(?m:^)latl.+=\s*(\d.+)(?:\v|$)+", 3) If NOT @Error <> 2 Then _ArrayDisplay($aLatLong);; Just for testing purposes Else MsgBox(4096, "Error", "The expression did not match any data in the file.") EndIf George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!"
Mellon Posted March 16, 2011 Author Posted March 16, 2011 I suspect that will work. However, regular expressions make my teeth bleed. The benefit of my coding is that, should I need it or something like it again I can support it.
z0mgItsJohn Posted March 16, 2011 Posted March 16, 2011 (edited) I'm pretty sure this is what you're looking for : #Include <File.au3> $File = '' For $A = 1 To _FileCountLines ($File) $Line = FileReadLine ($File, $A) If StringInStr ($Line, 'Type = Mark') Then FileWriteLine ('Export.txt', FileReadLine ($File, $A + 6)) Next Hope this helps, - John Edited March 16, 2011 by z0mgItsJohn Latest Projects :- New & Improved TCP Chat
Moderators SmOke_N Posted March 16, 2011 Moderators Posted March 16, 2011 (edited) I'm pretty sure this is what you're looking for : #Include <File.au3> $File = '' For $A = 1 To _FileCountLines ($File) $Line = FileReadLine ($File, $A) If StringInStr ($Line, 'Type = Mark') Then FileWriteLine ('Export.txt', FileReadLine ($File, $A + 6)) Next Hope this helps, - John Ouch, that's really inefficient . I'll try to explain why: 1. _FileCountLines: FileOpen, FileRead, FileClose, StringSplit, return array upper bound ( I assume this is how count lines works, haven't looked ) 2. FileReadLine: FileOpen, read line, FileClose ( every single loop ) 3. FileReadLine: FileOpen, read line + 6, FileClose ( every single loop, and past EOF for last 5 lines of the file ) 4. FileWriteLine: FileOpen, write line, FileClose ( every single loop ) Now the above ( on semi large or many files ) would take an extremely long time for all that extra opening, closing, reading, writing... Might try the same concept ( I'm not sure if it's what the OP wanted, I'm only showing your code change ), with less overhead: Func _myFunction($s_filein, $s_filewriteto) ; 1 file open, read, close Local $s_fread = FileRead($s_filein) If Not $s_fread Then Return SetError(1, 0, 0) ; get lines of file ( this works if the file uses CRLF or at least LF ; for line separators Local $a_lines = StringSplit(StringStripCR($s_fread), @LF) Local $s_output = "" For $iline = 1 To $a_lines[0] - 6 ; make sure the line is not null, then match string ; speed boost making sure it's not blank If $a_lines[$iline] And StringInStr($a_lines[$iline], "Type = Mark") Then $s_output &= $a_lines[$iline + 6] & @CRLF EndIf Next If Not $s_output Then Return SetError(2, 0, 0) ; 1 file open, write, close FileWrite($s_filewriteto, $s_output) Return 1 EndIf This code is untested, I wrote it in this little post pane, more for concept than anything. Edited March 16, 2011 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
Chimaera Posted March 16, 2011 Posted March 16, 2011 Im curious now I have a similar situaton but i have 6 users to check instead of one Mark, Ted, Gary, Bob, Hannah and Matt I suppose i could make 6 functions but there must be a better way than that? If Ive just helped you ... miracles do happen. Chimaera CopyRobo() * Hidden Admin Account Enabler * Software Location From Registry * Find Display Resolution * _ChangeServices()
hannes08 Posted March 16, 2011 Posted March 16, 2011 (edited) Hi Chimaera,I suppose you could replace:If $a_lines[$iline] And StringInStr($a_lines[$iline], "Type = Mark") Thenwith a Regular expression, e.g. StringRegExp($a_lines[$iline],"(Type = Mark|Type = Peter)"). Edited March 16, 2011 by Hannes123 Regards,Hannes[spoiler]If you can't convince them, confuse them![/spoiler]
Chimaera Posted March 16, 2011 Posted March 16, 2011 Like this you mean? Func _myFunction($s_filein, $s_filewriteto) ; 1 file open, read, close Local $s_fread = FileRead($s_filein) If Not $s_fread Then Return SetError(1, 0, 0) ; get lines of file ( this works if the file uses CRLF or at least LF ; for line separators Local $a_lines = StringSplit(StringStripCR($s_fread), @LF) Local $s_output = "" For $iline = 1 To $a_lines[0] - 6 ; make sure the line is not null, then match string ; speed boost making sure it's not blank StringRegExp($a_lines[$iline],"Mark", "Ted", "Gary", "Bob", "Hannah", "Mat") Then $s_output &= $a_lines[$iline + 6] & @CRLF EndIf Next If Not $s_output Then Return SetError(2, 0, 0) ; 1 file open, write, close FileWrite($s_filewriteto, $s_output) Return 1 EndIf If Ive just helped you ... miracles do happen. Chimaera CopyRobo() * Hidden Admin Account Enabler * Software Location From Registry * Find Display Resolution * _ChangeServices()
hannes08 Posted March 16, 2011 Posted March 16, 2011 Hi Chimaera, This won't work. Maybe you want to try this way: $pattern = "(Type = Mark|Type = Peter|Type = Ted|Type = Mat|Type = Bob)" If $a_lines[$iline] And StringInStr($a_lines[$iline], $pattern) Then ; Do something End If Regards,Hannes[spoiler]If you can't convince them, confuse them![/spoiler]
Mellon Posted March 16, 2011 Author Posted March 16, 2011 All of which begs my question. Why does my script work correctly for the first record and then fail for all the rest?
Developers Jos Posted March 16, 2011 Developers Posted March 16, 2011 (edited) All of which begs my question. Why does my script work correctly for the first record and then fail for all the rest? You move the filepointer 6 records forward but do not add 6 to $w. try below that has some debug lines in it so you can see what is happening: $w=0 $WhattoOpen=FileOpen("Export.Txt",0) $WhattoWriteto=fileopen("NobeltechMark.psv",1) While 1 $Checktheline=FileReadLine($WhattoOpen) ; read a line from the file If @error then ExitLoop $W += 1 ConsoleWrite('@@ Debug : $W = ' & $W & ' $Checktheline = ' & $Checktheline & @crlf) ;### Debug Console $IsitaMark=StringInStr($Checktheline,"Type = Mark") ;find out if it is a mark record If $IsitaMark <> 0 Then $Thisisthelatlon=FileReadLine($whattoopen,$w+6) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Thisisthelatlon = ' & $Thisisthelatlon & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console filewrite($WhattoWriteto,$Thisisthelatlon & @CRLF) $W += 6 $isitamark=0 endif WEnd ps... the posted code would never end as you do not check for EOF... Jos Edited March 16, 2011 by Jos 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.Â
Moderators SmOke_N Posted March 16, 2011 Moderators Posted March 16, 2011 (edited) One, my apologies for not directly looking at your issue in my previous post. Your text file looks like nothing more than an ini file to me. This could solve your issue, however, I'm not a fan of it still opening and closing all the time, but it's a simple solution. #include <array.au3> ; for _arraydisplay only Global $gs_file = "test.txt" Global $ga_lonslats = _myGetLatLon($gs_file, "Mark") If IsArray($ga_lonslats) Then ConsoleWrite("Found " & $ga_lonslats[0] & " longitudes and latitudes." & @CRLF) _ArrayDisplay($ga_lonslats) ; Now you could enum through the array and write to the file if you wanted. EndIf Func _myGetLatLon($s_filein, $s_type) Local $a_secnames = IniReadSectionNames($s_filein) If @error Or Not IsArray($a_secnames) Then Return SetError(1, 0, 0) ; return array of longitudes and latitudes Local $a_ret[$a_secnames[0] + 1], $i_add = 0 For $iname = 1 To $a_secnames[0] If IniRead($s_filein, $a_secnames[$iname], "Type", "") = $s_type Then $i_add += 1 $a_ret[$i_add] = IniRead($s_filein, $a_secnames[$iname], "LatLon", "") EndIf Next If Not $i_add Then Return SetError(2, 0, 0) ReDim $a_ret[$i_add + 1] $a_ret[0] = $i_add Return $a_ret EndFunc Another method you might look at is regex ( quick and dirty ): #include <array.au3> ; for _arraydisplay only Global $gs_file = "test.txt" Global $ga_lonslats = _myGetLatLon2($gs_file, "Mark") If IsArray($ga_lonslats) Then ConsoleWrite("Found " & $ga_lonslats[0] & " longitudes and latitudes." & @CRLF) _ArrayDisplay($ga_lonslats) ; Now you could enum through the array and write to the file if you wanted. EndIf Func _myGetLatLon2($s_filein, $s_type) Local $s_fread = FileRead($s_filein) If $s_fread = "" Then Return SetError(1, 0, 0) Local $s_pattern = "(?is)(?:\A|\v)Type\s*=\s*\Q" & $s_type & "\E" $s_pattern &= "\s*\v.+?\vLatLon\s*=\s*(.+?)\s*(?:\v|\z)" Local $a_sre = StringRegExp($s_fread, $s_pattern, 3) If @error Then Return SetError(2, 0, 0) ; comment out below if you want a zero base array and ; just return $a_sre ; convert to 1 base array where [0] has total number of indexes Local $i_ub = UBound($a_sre) Local $a_ret[$i_ub + 1] = [$i_ub] For $i = 0 To $i_ub - 1 $a_ret[$i + 1] = $a_sre[$i] Next Return $a_ret EndFunc Edited March 16, 2011 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.
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