Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Re: how to populate array with last 20 lines of file

by thanos1983 (Parson)
on Aug 09, 2017 at 10:23 UTC ( [id://1197095]=note: print w/replies, xml ) Need Help??


in reply to how to populate array with last 20 lines of file

Hello ytjPerl,

There is an alternative solution to your problem using module File::ReadBackwards

Sample of code bellow:

#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use File::ReadBackwards; my $numlines = 20; my $filename = 'in.log'; my $bw = File::ReadBackwards->new($filename) or die "can't read $filename $!"; my @lines; my $count = 0; while( defined( my $line = $bw->readline ) ) { chomp $line; push @lines, $line; $count++; last if $count == $numlines; } @lines = reverse @lines; print Dumper \@lines; __END__ $ perl reverse_file.pl $VAR1 = [ 'line 2', 'line 3', 'line 4', 'line 5', 'line 6', 'line 7', 'line 8', 'line 9', 'line 10', 'line 11', 'line 12', 'line 13', 'line 14', 'line 15', 'line 16', 'line 17', 'line 18', 'line 19', 'line 20', 'line 21' ];

Sample of in.log for testing purposes:

line 1 line 2 line 3 line 4 line 5 line 6 line 7 line 8 line 9 line 10 line 11 line 12 line 13 line 14 line 15 line 16 line 17 line 18 line 19 line 20 line 21

As a next step you can apply a grep or a regex on the lines that you have collected and do what ever you want with the process.

Update: I would use flock to lock the file as it is important not get mixed on an instance that data are populated on the file. Sample of code bellow:

#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use File::ReadBackwards; # import LOCK_* and SEEK_END constants use Fcntl qw(:flock SEEK_END); sub lock { my ($fh) = @_; flock($fh, LOCK_EX) or die "Cannot lock mailbox - $!\n"; # and, in case someone appended while we were waiting... seek($fh, 0, SEEK_END) or die "Cannot seek - $!\n"; } sub unlock { my ($fh) = @_; flock($fh, LOCK_UN) or die "Cannot unlock mailbox - $!\n"; } my $numlines = 20; my $filename = 'in.log'; my $bw = File::ReadBackwards->new($filename) or die "can't read $filename $!"; my $fh = $bw->get_handle(); lock($fh); my @lines; my $count = 0; while( defined( my $line = $bw->readline ) ) { chomp $line; push @lines, $line; $count++; last if $count == $numlines; } unlock($fh); $bw->close(); @lines = reverse @lines; print Dumper \@lines; __END__ $ perl reverse_file.pl $VAR1 = [ 'line 2', 'line 3', 'line 4', 'line 5', 'line 6', 'line 7', 'line 8', 'line 9', 'line 10', 'line 11', 'line 12', 'line 13', 'line 14', 'line 15', 'line 16', 'line 17', 'line 18', 'line 19', 'line 20', 'line 21' ];

Update2: In case you want to loop again and again the file in reverse mode you can apply something like that. Sample of code bellow:

#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use File::ReadBackwards; # import LOCK_* and SEEK_END constants use Fcntl qw(:flock SEEK_END); sub lock { my ($fh) = @_; flock($fh, LOCK_EX) or die "Cannot lock mailbox - $!\n"; # and, in case someone appended while we were waiting... seek($fh, 0, SEEK_END) or die "Cannot seek - $!\n"; } sub unlock { my ($fh) = @_; flock($fh, LOCK_UN) or die "Cannot unlock mailbox - $!\n"; } sub check_file { my ($file, $numlines) = @_; my $bw = File::ReadBackwards->new($file) or die "can't read $file $!"; my $fh = $bw->get_handle(); lock($fh); my @lines; my $count = 0; while( defined( my $line = $bw->readline ) ) { chomp $line; push @lines, $line; $count++; last if $count == $numlines; } unlock($fh); $bw->close(); return reverse @lines; } my @data; my $numlines = 20; my $process = "line 2"; my $filename = 'in.log'; while ( 1 ) { @data = check_file($filename, $numlines); last if (grep /$process/, @data); sleep 5; } print Dumper \@data; __END__ $ perl reverse_file.pl $VAR1 = [ 'line 2', 'line 3', 'line 4', 'line 5', 'line 6', 'line 7', 'line 8', 'line 9', 'line 10', 'line 11', 'line 12', 'line 13', 'line 14', 'line 15', 'line 16', 'line 17', 'line 18', 'line 19', 'line 20', 'line 21' ];

Update3 Last Update: Similar solution different way of writing it, just for fun and preference. Sample of code bellow:

do { @data = check_file($filename, $numlines); sleep 5; } while ( grep not /$process/, @data );

Hope this helps, BR.

Seeking for Perl wisdom...on the process of learning...not there...yet!

Replies are listed 'Best First'.
Re^2: how to populate array with last 20 lines of file
by ytjPerl (Scribe) on Aug 09, 2017 at 14:12 UTC
    It is definitely helpful. I will try them all to see which solution works best to meet my needs. I really appreciate that. very thoughtful.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1197095]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (4)
As of 2024-04-19 04:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found