AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Tail: the last lines of a text file

 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Laszlo



Joined: 14 Feb 2005
Posts: 4668
Location: Boulder, CO

PostPosted: Fri Dec 16, 2005 3:37 pm    Post subject: Tail: the last lines of a text file Reply with quote

The last few lines of a text file are often needed, like at checking a log file for a specific entry. Here is a short script for it.
Code:
Tail(k,file)   ; Return the last k lines of file
{
   Loop Read, %file%
   {
      i := Mod(A_Index,k)
      L%i% = %A_LoopReadLine%
   }
   L := L%i%
   Loop % k-1
   {
      IfLess i,1, SetEnv i,%k%
      i--      ; Mod does not work here
      L := L%i% "`n" L
   }
   Return L
}
Test it with
Code:
MsgBox % Tail(3, A_ScriptFullPath)
For only the last line of a file, the following 2-line script is enough
Code:
Loop Read, %A_ScriptFullPath%
   L = %A_LoopReadLine%

For small files the following version might be faster (Serenity's solution). It reads the file into a variable and parses it from memory. For large files the version above is better, because it scans the file only once, and keeps only k lines in memory.
Code:
Tail(k,file)   ; Return the last k lines of file
{
   FileRead text, %file%
   Loop Parse, text, `n
     lines++
   Loop Parse, text, `n
   {
      If (A_Index < lines - k)
         Continue
      L = %L%`n%A_Loopfield%
   }
   StringTrimLeft L, L, 1
   Return L
}
Back to top
View user's profile Send private message
pin
Guest





PostPosted: Fri Dec 16, 2005 4:07 pm    Post subject: Reply with quote

Bookmarked!
Can i ask a question here? How to loop and send msgbox when file size is changed, or new lines are added to current %file%.
ie: when log.txt is changed(new lines are added) it send msgbox
Back to top
Laszlo



Joined: 14 Feb 2005
Posts: 4668
Location: Boulder, CO

PostPosted: Fri Dec 16, 2005 5:45 pm    Post subject: Reply with quote

Code:
#Persistent
Settimer FileCheck

FileCheck:
   FileGetSize Size, %A_ScriptFullPath%   ; put your filename here
   If Size0 >= %Size%
      Return
   If Size0 =
   {
      Size0 = %Size%
      Return
   }
   MsgBox File size increased!
   Size0 = %Size%
Return
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 950

PostPosted: Sun Apr 12, 2009 9:50 am    Post subject: Reply with quote

I posted at an other thread a version without loop and regex. May be you are interested in testing. Not sure how faster (or slower) it can be.
http://www.autohotkey.com/forum/viewtopic.php?t=43104

This is the one getting last line only:
Code:
str_getTailf(ByRef _Str) {
    Return SubStr(_Str,InStr(_Str,"`n",False,0)+1)
}


This is the one with n lines (here called _LineNum):
Code:
str_getTail(_Str, _LineNum = 1)
{
    StringGetPos, Pos, _Str, `n, R%_LineNum%
    StringTrimLeft, _Str, _Str, % ++Pos
    Return _Str
}
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 950

PostPosted: Sun Apr 12, 2009 10:55 am    Post subject: Reply with quote

Here is a comparison of the functions.

Anyway here is my benchmark result:

Quote:
Code:
str_getTailf (by Tuncay):      188
str_getTail (by Tuncay):      469
StrTail /loop (by strictlyfocused02):   16750
Tail /regex (by Laszlo):      1062


This is the script and the functions used to benchmark:
Code:
Text := "`n`n`n"
Loop, 100000
    Text .= "`nLine " . A_Index

StartTime := A_TickCount
Loop, 100
str_getTailf(Text)
ElapsedTime1 := A_TickCount - StartTime

StartTime := A_TickCount
Loop, 100
str_getTail(Text)
ElapsedTime2 := A_TickCount - StartTime

StartTime := A_TickCount
Loop, 100
StrTail(1,Text)
ElapsedTime3 := A_TickCount - StartTime

StartTime := A_TickCount
Loop, 100
Tail(1,Text)
ElapsedTime4 := A_TickCount - StartTime

out =
(
str_getTailf (by Tuncay):`t`t%ElapsedTime1%
str_getTail (by Tuncay):`t`t%ElapsedTime2%
StrTail /loop (by strictlyfocused02):`t%ElapsedTime3%
Tail /regex (by Laszlo):`t`t%ElapsedTime4%
)
MsgBox, 1, Benchmark results, Ok copies to clipboard`n`n%out%
IfMsgBox Ok
    Clipboard := out

RETURN

str_getTailf(ByRef _Str) {
    Return SubStr(_Str,InStr(_Str,"`n",False,0)+1)
}

str_getTail(_Str, _LineNum = 1)
{
    StringGetPos, Pos, _Str, `n, R%_LineNum%
    StringTrimLeft, _Str, _Str, % ++Pos
    Return _Str
}

StrTail(k,str) ;; Inspired by Laszlo (http://www.autohotkey.com/forum/topic6928.html)
   {
   Loop,Parse,str,`n
      {
      i := Mod(A_Index,k)
      L%i% = %A_LoopField%
      }
   L := L%i%
   Loop,% k-1
      {
      If i < 1
         SetEnv,i,%k%
      i-- ;Mod does not work here
      L := L%i% "`n" L
      }
   Return L
   }

Tail(k,str) {
      Return RegExReplace(str,".*(?=(\n[^\n]*){" k "}$)")
}


edit: updated the Tail function from Laszlo


Last edited by Tuncay on Sun Apr 12, 2009 6:27 pm; edited 2 times in total
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4668
Location: Boulder, CO

PostPosted: Sun Apr 12, 2009 4:41 pm    Post subject: Reply with quote

The point of this 3.5 years old thread was to get the last line of a text file, without keeping the whole file in memory. Even if the file fits to the RAM, the memory usage gets large, which may cause other applications to slow down.

During the last three years we learned how to seek and read only portions of the file, so there are much faster methods for huge files.
Back to top
View user's profile Send private message
Tuncay



Joined: 07 Nov 2006
Posts: 950

PostPosted: Sun Apr 12, 2009 4:48 pm    Post subject: Reply with quote

Oh I did not looked at the date... how I came to this thread??
Back to top
View user's profile Send private message
vla



Joined: 12 May 2007
Posts: 28

PostPosted: Thu May 14, 2009 8:12 pm    Post subject: Reply with quote

Code:
Text =
(
Text of Line 1
Text of Line 2
Text of Line 3
Text of Line 4
Text of Line 5
Text of Line 6
Text of Line 7
Text of Line 8
Text of Line 9
Text of Line 10
Text of Line 11
Text of Line 12
Text of Line 13
Text of Line 14
Text of Line 15
)

MsgBox,% StrTail(4,Text)

;Return the last (k) lines of (str)
StrTail(k,str) ;; Inspired by Laszlo (http://www.autohotkey.com/forum/topic6928.html)
   {
   Loop,Parse,str,`n
      {
      i := Mod(A_Index,k)
      L%i% = %A_LoopField%
      }
   L := L%i%
   Loop,% k-1
      {
      If i < 1
         SetEnv,i,%k%
      i-- ;Mod does not work here
      L := L%i% "`n" L
      }
   Return L
   }


Using that code how do i get the var "text" to be a file? I do not fully understand this code, i am changing a few things to see what happens.
Changing the MsgBox,% StrTail(4,Text) into a 1 i get the last line, but what var is that saved under? %strtail?


i figured out the first question, use fileread. Still don't know exactly how the variable on that works.
Back to top
View user's profile Send private message AIM Address
Laszlo



Joined: 14 Feb 2005
Posts: 4668
Location: Boulder, CO

PostPosted: Thu May 14, 2009 8:51 pm    Post subject: Reply with quote

It is a function call, its result is not saved, unless you write something like
Code:
MyVar := StrTail(4,Text)
Back to top
View user's profile Send private message
vla



Joined: 12 May 2007
Posts: 28

PostPosted: Thu May 14, 2009 8:54 pm    Post subject: Reply with quote

perfect! thank you so much, i love you all.
Back to top
View user's profile Send private message AIM Address
Laszlo



Joined: 14 Feb 2005
Posts: 4668
Location: Boulder, CO

PostPosted: Thu May 14, 2009 9:08 pm    Post subject: Reply with quote

btw, you can write the original function more compactly
Code:
Tail(k,file) {  ; Return the last k lines of file
   Loop Read, %file%
      i := Mod(A_Index,k), L%i% := A_LoopReadLine
   Loop % k
      i := Mod(i+1,k), L .= L%i% "`n"
   Return L
}
Back to top
View user's profile Send private message
guest3456
Guest





PostPosted: Mon Jun 07, 2010 4:43 am    Post subject: Reply with quote

Laszlo wrote:

During the last three years we learned how to seek and read only portions of the file, so there are much faster methods for huge files.


i found this one:

http://de.autohotkey.com/forum/topic4619.html
Back to top
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group