Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??
In response to this SoPW node, I felt compelled to invent something simple and quick that would scan a perl script and report any cases where "my" was used to declare the same variable name more than once.

This approach is not subtle or discerning -- just check all easily-identifyable uses of "my" with variable names, and keep these (with line numbers) in a hash. When done scanning the script, report the cases with more than one line number. (There is also the "--listall" option, which does what you would expect...)

Caveats (at least, the ones I know of):

  • The line numbers being reported are based on the output of B::Deparse, where all commentary has been stripped, and spacing and punctuation have been normalized. This means you may need to work a little harder to relate this diagnosis to your original script, but doing it this way helps me make the search for "my" a lot less speculative (and I do save the Deparsed version of the script in a separate file, so you can actually use the line-number info that is being given).
  • There are bound to be other ways that "my" shows up in a "deparsed" script besides the ones being searched for in this version, so there may be some "misses".
  • Someone is bound to try this on a script containing a quoted literal string that looks like a "my" declaration, so there may be some false alarms as well.
  • This doesn't pay any attention to scope. If you use anything like  foreach my $arg ( @list ) in multiple places in your script, and these are all sensible and proper, this diagnosis will cite them all as "repeats" anyway -- better to be stupid and safe, I think.

That said, here's the code (tested on a few scripts):

#!/usr/bin/perl # Program: scan-perl-vars.perl # Written by: dave graff # Purpose: look for and summarize the declarations and calls # of lexically-scoped variables in a perl script use strict; my $Usage = "$0 [--listall] my_script.perl\n". " will list 'my' vars that have been declared more than once in a +script\n". " (with --listall, will list all lexical variables, with line numb +ers)\n"; my $listyp = ' more than once'; if ( @ARGV > 1 and $ARGV[0] eq '--listall' ) { $listyp = ''; shift; } die $Usage unless ( @ARGV == 1 && -r $ARGV[0] ); my $erlog = "/tmp/scn-src.$$.errlog"; my $file = shift; warn "Deparsing $file...\n"; my @lines = `perl -MO=Deparse,-p $file 2> $erlog`; die "Nothing deparsed from $file -- sorry.\n" unless ( @lines ); my $log = `cat $erlog`; die "Syntax errors in $file -- come back when you're ready.\n" unless ( $log =~ /^$file syntax OK/ ); # Store an array of subroutine defs in a hash element # keyed by file name: my %vardecs; # HoA keyed by var name, stores line #(s) of declaration +(s) my $lineno = 0; open( DP, ">$file.deparse" ) or warn "couldn't write deparsed code to +$file.deparse:$!\n"; foreach (@lines) { $lineno++; print DP "$lineno\t$_"; while (( my $nxt = index( $_, 'my' )) >= 0 ) { if ( /\bmy\(([^\)]+)/ ) { foreach my $name (split(/,/,$1)) { push @{$vardecs{$name}}, $lineno; } } elsif ( /\bmy\s+([\%\$\*\@]\S+)/ ) { push @{$vardecs{$1}}, $lineno; my $nxt = 0; } $_ = substr( $_, $nxt+3 ); } } close DP; # Now do some reporting die "No lexically-scoped variables in $file\n" unless ( keys %vardecs +); my $nlisted = 0; foreach (sort keys %vardecs) { next unless ( scalar @{$vardecs{$_}} > 1 or $listyp eq ''); print join( ' ', $_, @{$vardecs{$_}}, "\n" ); $nlisted++; } print "\nTotal of $nlisted 'my' variables declared$listyp in $file\n"; print "(see $file.deparse for correct line-number references)\n" if ( $nlisted );

In reply to Check a perl script for repeat "my" declarations by graff

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    [marto]: Good morning all

    How do I use this? | Other CB clients
    Other Users?
    Others about the Monastery: (5)
    As of 2018-04-21 06:38 GMT
    Find Nodes?
      Voting Booth?