36. Another Perl Example Explained
open(FILE, "/usr/sbin/traceroute -n $ARGV[0] 2>/dev/null|");
Open the traceroute command to get its output. Notice that
the IP will have to be passed into the script, and that the
standard error has been piped to /dev/null (because traceroute
outputs its first line {that I didn't want displayed} to STDOUT).
while (<FILE>) {
$data = $_;
While traceroute still producing output, put each line (one line
at a time for this example!) into $data.
if ($data =~ m/^\s?\d+\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+([0-9.]* ms|
\*)\s+([0-9.]* ms|\*)\s+([0-9.]* ms|\*)/) {
Here's our big regex! We are trying to match:
- The start of the line
- Followed by an optional space
- Followed by one or more digits (this is the hop number).
By default traceroute only does 30 hops, so \d{1,2} would
have been just as good here, but because there is always
a space after the hop number, it doesn't really matter.
- Followed by one of more spaces
- Followed by a series of 4 sets of 1 to 3 digits, separated
by literal dots. This is the IP address of the hop. Notice
we used traceroute -n to ensure that the IP form would be
used! Notice also the IP address is grouped with brackets
so we can use it later.
- Followed by one or more spaces
- Followed by zero or more of the characters 0-9 and literal dot,
then a space, then the literal "ms" (for the time of the hop in
milliseconds, OR a literal star when there was no response or a
timeout on the hop. Note: Yes, there's options left out here!
What if we got a "!H" back? Or a time in something other than
milliseconds? It all comes down to what you are doing - in the
case I wrote this for, these were very unlikely to occur,
so I didn't bother to worry about these options (not that to
do so would be very hard). It all comes down to what you know
about your data, and matching what you want vs. what you don't.
- Followed by one or more spaces, and the above again, etc.
Then we assign $1, $2, $3 and $4 to variables (so we can channge them -
backreference variables are not editable in Perl).
$a =~ s/ ms//;
$b =~ s/ ms//;
$c =~ s/ ms//;
We have to trim the " ms" from the times so that we can add them together -
so here we see the use of a regex to do a search and replace. Perl does
this using "s/regex/replace/". In this case, we search for the " ms" and
replace it with nothing!
And we finish up with some adding, averaging and displaying - all pretty
normal Perl stuff.
|