#!/usr/bin/perl # Filename: spigot # Author: David Ljung Madison # See License: http://MarginalHacks.com/License/ my $VERSION= '1.00'; # Description: Like a faucet tap, turns the output of a text file on and off use strict; ################################################## # Setup the variables ################################################## my $PROGNAME = $0; $PROGNAME =~ s|.*/||; my ($BASENAME,$PROGNAME) = ($0 =~ m|(.*)/(.+)|) ? ($1?$1:'/',$2) : ('.',$0); ################################################## # Usage ################################################## sub fatal { foreach my $msg (@_) { print STDERR "[$PROGNAME] ERROR: $msg\n"; } exit(-1); } sub usage { foreach my $msg (@_) { print STDERR "ERROR: $msg\n"; } print STDERR < Like a faucet tap, turns the output of a text file on and off Controls: -show Show lines -skip Skip lines -off Turn off display when is seen -on Turn on display when is seen -ON Just turn on (similar to '-on .') -OFF Just turn off -d Set debug mode Examples: # A very inefficient 'cat' % $PROGNAME file # Like 'head' % $PROGNAME file -show 15 -OFF # Show everything up until '^footer' is seen % $PROGNAME file -off '^footer' # Show everything up until and including '^footer' # (The '-show 1' will show one line (the footer) but won't change on/off status) % $PROGNAME file -off '^footer' -show 1 # Show everything after we find 'START' % $PROGNAME file -OFF -on START # Show everything after (but not including) 'START' % $PROGNAME file -OFF -on START -skip 1 # Show the first two lines of 'log' then show everything from 'ERROR MSG' # until the first blank line is found, then stop processing the file % $PROGNAME log -OFF -show 2 -on "ERROR MSG" -off '^\$' USAGE exit -1; } sub parse_args { my $opt = {}; while (my $arg=shift(@ARGV)) { if ($arg =~ /^-h$/) { usage(); } if ($arg =~ /^-d$/) { $MAIN::DEBUG=1; next; } if ($arg =~ /^-(on|show|skip|off)$/) { push(@{$opt->{ctrl}}, [$1, shift @ARGV]); next; } if ($arg =~ /^-(ON|OFF)$/) { push(@{$opt->{ctrl}}, [$1]); next; } if ($arg =~ /^-./) { usage("Unknown option: $arg"); } push(@{$opt->{files}}, $arg); } usage("No file defined") unless $opt->{files}; $opt; } sub debug { return unless $MAIN::DEBUG; foreach my $msg (@_) { print STDERR "[$PROGNAME] $msg\n"; } } ################################################## # Process a file ################################################## # Do we start with the spigot on or off? sub start { my ($opt, $ctrl) = @_; return 1 unless $ctrl; my $cmd = $ctrl->[0]; return 1 unless $cmd; return 0 if grep($cmd eq $_, qw(show on)); 1; } sub process { my ($opt, $file) = @_; my @ctrl = $opt->{ctrl} ? @{$opt->{ctrl}} : (); open(FILE,"<$file") || usage("Couldn't open file: $file"); # Process a file, turning the spigot on and off. my $on = start($opt, @ctrl); while() { # Can we match any controls? my $match = 1; while ($match) { # We're done if we're 'off' and we have no more controls unless (@ctrl) { if ($on) { print; map { print } ; } last; } # Get the next control my ($cmd,$arg,@args) = @{$ctrl[0]}; $match = 0; if ($cmd eq "ON") { ($on,$match) = (1,1); } elsif ($cmd eq "OFF") { ($on,$match) = (0,1); } elsif ($cmd eq "on") { ($on,$match) = (1,1) if /$arg/; } elsif ($cmd eq "off") { ($on,$match) = (0,1) if /$arg/; } elsif ($cmd eq "show") { print; # Current line map { print scalar ; } 2..$arg; $_ = scalar ; # Next line $match = 1; } elsif ($cmd eq "skip") { map { scalar ; } 2..$arg; $_ = scalar ; # Next line $match = 1; } shift(@ctrl) if $match; } print if $on; } close(FILE); } ################################################## # Main code ################################################## sub main { my $opt = parse_args(); map { process($opt, $_) } @{$opt->{files}}; } main();