On Tue, Jun 10, 2003 at 11:49:25PM -0700 Harry Putnam wrote:

> I use a homeboy data base technique to keep info about the scripts I
> write and other typse of stuff too.  Here I'm just dealing with
> scripts.
> 
> Its a simple format to enter key information about what a script
> does.  Looks like:
> 
> # Keywords: SOME WORDS
> # body
> # body
> # DATE
> # &&
> 
> I've written various scripts to search this format in awk and shell.
> Now trying it in perl.  I have several working scripts but wanted to
> get some ideas from the sharp shooters here how to do this better.
> 
> My technique seems like it could be streamlined and improved quite a
> lot.

Yes, it's a little wordy considering it's Perl.

> The sample below just handles the basic technique and isn't completed
> with all tests and etc.  Just some basic ones. But really I'm more
> interested in hearing better ways to accomplish this.
> 
> The basic task is to locate a formated segment, search its keywords
> line for regex then print the segment.  Also a basic check for
> misformatted segments.
> 
> Not too concerned with how the files are aquired but what comes after.
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> #!/usr/local/bin/perl -w
> 
> ($myscript = $0) =~ s:^.*/::; 

You are allowed to manipulate $0, too. The new value of $0 is the one
that is eventually showing up in your process-table (unless you are
using Perl5.8.0 where this does not work due to a bug).

> $regex = shift;
> ## Set Keywords start end regex for non script searching (The default)
> $keyreg = '^# Keywords:';
> $keyend = '^# &&$';
> 
> if (!$ARGV[0]) {
>   usage();
>   exit;
> }
> ## Aquire there files in whatever way
> @files = @ARGV;
> 
> ## Set a marker to know when we are in a new file
> $fname_for_line_cnt = '';
> for (@files) { 
>   chomp;

I don't think that the entries in @ARGV contain newlines at the end.
Actually I know they don't. :-)

>   $file = $_;
>   if ("$fname_for_line_cnt" eq "$file") {

There is no reason to put those variables into quotes.

>    ## This shouldn't happen
>     print "We're reading the same file again .. exiting\n";
>     exit;

That is better solved using a hash. Fill all the files into a hash (as
keys) and iterate over the keys. That way, it's guaranteed you only
inspect each file once.

>   } else {
>     ## Set lineno to 0 for start of each file
>     $lineno = 0;
>     $fname_for_line_cnt = $file;
>   }
> 
>   if (-f $file) {
>     open(FH,"<$file") or die "Cannot open $file: $!";
>     while (<FH>) {
>       chomp;
>       $lineno++;

You don't have to keep track of the line numbers yourself. Perl offers
the special variable $. for that.

>       $line = $_;
>       if (/$keyreg $regex/) {
>         print "$file\n";
>       $hit = "TRUE";
>       }
>       if ($hit) {
>       print "$lineno $line\n";
>       }
>       if ($hit && /$keyend/) {
>       ## We've hit the end of a good segment, print delimiter and null
>       ## out our vars
>       print "-- \n";
>       $hit        = '';
>       $line       = '';
>       }
>       if ($hit && /^[^#]/ || $hit && eof) {
>         ## If we see this situation it means the format is screwed up
>         ## Notify user of the line number, but null out vars and proceed. 
>       print  "$file:\n   INCOMPLETE SEGMENT ENTRY: Line <$lineno>\n --\n";
>       $hit        = '';
>       $line       = '';
>       }
>     }
>     close(FH);
>   } else {
>     next;
>   }
> }
> sub usage {
>   print<<EOM;
> 
> Purpose: Search scripts keyword segments (or any file)
> Usage: \`$myscript "REGEX" file ... fileN (or glob)'
>       (Where REGEX is a regex to be found in Keyword segment) 
> 
> EOM
> }

I'd probably write it like that:

    #!/usr/local/bin/perl -w
    use strict;
    
    $0 =~ s:.*/::;
    
    my $regex = shift;
    $regex = qr/^# Keywords: $regex/;   # could improve performance a little
    
    my %files;
    @files{ @ARGV } = ();               # a hash-slice: see 'perldoc perldata'
    
    usage(), exit if ! @ARGV;

    for my $file (keys %files) {
        next if ! -f $file;
        open FILE, "<", $file or die "Error opening $file: $!";

        my $hit;
        while (<FILE>) {        
            chomp;
            $hit++ if /$regex/o;        # start of record
            print "$. $_\n" if $hit;    # $. is the line number        
            $hit-- if /^# &&$/;         # end of record
            print "$file:\n\tINCOMPLETE SEGMENT ENTRY: Line <$l.>\n--\n"
                and $hit--
                if $hit && !/^#/ or $hit && eof;
        }
    }

    sub usage {
        ...
    }
       
I didn't test it but it should produce the same result as your script
and doing it considerably more quickly. Please substract any possible
syntax errors or logical flaws from the script before running it. ;-)

Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval


-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to