Hello Monks!
Spent a few hours at work on several occasions debugging some scripts that are almost as old as I am, and have found a quirk that I don't really understand.
Essentially, we pull a "string of numbers" from an argument given at the command line, and then do various things based on what's contained in that string.
An example of the borked code is as follows:
#!/usr/bin/perl
# I know there should be
# use strict;
# and
# use warnings;
sub process {
my ($fileName) = @_;
open FILE, $fileName or die $!;
while (<FILE>) {
chomp $_;
my @parts = split(',', $_);
for (@parts) {
# Do some stuff
}
}
}
sub finalize {
print "Finished\n";
}
my $runlvl = $ARGV[0];
if ($runlvl == 1) {
# Do everything
$runlvl = "23";
}
die "Invalid arguments"
unless ($runlvl =~ /^\d+$/);
# For conversations sake, lets just read this script
my $filename = $0;
print "Run level: $runlvl\n";
# Do some stuff based on the runlevel
for ($runlvl) {
/2/ and process($filename);
/3/ and finalize();
}
print "Run level: $runlvl\n";
When I run this with a single command line parameter of "1", I'd expect it to get to that poor-man's switch at the bottom and do a process() and finalize(), however only the "2" matches. By the time it gets to the "3", $runlvl is empty.
The output of the above is:
$ perl broken.pl 1
Run level: 23
Run level:
Though it took a while to figure out where things were going pear-shaped, the below seems to work as expected. Note the difference in the while() loop in that first subroutine
#!/usr/bin/perl
sub process {
my ($fileName) = @_;
open FILE, $fileName or die $!;
while (my $line = <FILE>) {
chomp $line;
my @parts = split(',', $line);
for (@parts) {
# Do some stuff
}
}
}
sub finalize {
print "Finished\n";
}
my $runlvl = $ARGV[0];
if ($runlvl == 1) {
# Do everything
$runlvl = "23";
}
die "Invalid arguments"
unless ($runlvl =~ /^\d+$/);
# For conversations sake, lets just read this script
my $filename = $0;
print "Run level: $runlvl\n";
# Do some stuff based on the runlevel
for ($runlvl) {
/2/ and process($filename);
/3/ and finalize();
}
print "Run level: $runlvl\n";
Wahoo! This time it outputs:
$ perl not_broken.pl 1
Run level: 23
Finished
Run level: 23
So I guess the actual question I want to ask is why is that first while loop that uses the somewhat magick $_ rather than it's own local variable clobbering the value of $runlvl? Or is it clobbering @ARGV? Or.. Is that weird switch thing trying to match on $_ rather than "whatever is in runlevel"?
This ones got me stumped - any wisdom would be greatly appreciated.
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, details, 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, summary, 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: |
| & | | & |
| < | | < |
| > | | > |
| [ | | [ |
| ] | | ] |
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.