http://qs1969.pair.com?node_id=46427

MCauth has asked for the wisdom of the Perl Monks concerning the following question:

Hello: gonna keep it brief, as I've gotta get back to work. I wrote my own little "whois" program to iterate through a list of domains work wants me to confirm. Got the data w/out too much pain. Now, I've got to print a report. I've got the format looking the way I want it, but I'm getting huge amounts of duplicates from the loop. Any help would be GREATLY appreciated. Here's my code: (keep in mind I'm a neophyte, so it won't be pretty!!)

#!/usr/bin/perl -w OUTER: while (<>){ s/^\s+//; # trim off whitespace... next OUTER if /^$/; # ignore blank lines chomp; $registrant=$_ if (/Registrant:/../\)/); $domain_name=$_ if /Domain Name.*/; $admin=$_ if /Administrative Contact:/../\)/; $tech=$_ if /Technical Contact:/../\)/; $billing=$_ if /Billing Contact:/../\)/; $expires=$_ if /Record expires on .*/; if (/NAME\..+\s+\d{1,3}.\d{1,3}.\d{1,3}/){ s/Name Server: .*//; push @names, $_; next OUTER; } write STDOUT if defined($registrant and $admin and $tech and + $billing and $names[2] and $expires); } format STDOUT = ====================================================================== +========== @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Registrant: @<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<<<<<<< $domain_name , $registrant Admin: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<< $admin Tech: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<< $tech Billing: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<< $billing DNS: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<< $names[0] @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<<<<<<<< $names[1] @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<< $names[2]@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<< $expires ====================================================================== +========== .

.... I know the DNS portion of the above code is formatted poorly for this post, but it does work. For example, if I were to put in the output from a whois on "perlmonks.org," I'd end up with 18 or so duplicate reports. Any ideas? I'm sure it's a simple fix, but I've been looking at it for so long my brain is fried.
Thanks,
Matt

Replies are listed 'Best First'.
Re: A looping and format question...
by kilinrax (Deacon) on Dec 13, 2000 at 19:48 UTC
    Well, you're code's pretty rough, but i'll try and pinpoint the immediate problem:
    write STDOUT if defined($registrant and $admin and $tech and $billing +and $names[2] and $expires);
    If the above test evaluates to true, you should also exit the OUTER loop, thus;
    if defined($registrant and $admin and $tech and $billing and $names[2] + and $expires){ write STDOUT; last OUTER; }
    Otherwise the loop will keep on recurring and print your results several times.

    I would also suggest that a much better way of doing this would be to take the test out of the loop entirely.
    Also, you may want to take a look at the Net::Whois module.
Re: A looping and format question...
by turnstep (Parson) on Dec 13, 2000 at 20:48 UTC
    A large problem is that you seem to be assuming that:
    • A. Everyone you do a whois on is going to be registered with Network Solutions
    • B. Network Solutions will never change their format.

    Both are dangerous assumptions: I would definitely look at Net::Whois as mentioned above. It was made for this sort of thing.

    Nonetheless, here is a quick fix of the code above. Not the best, but a little more readable.

    #!/usr/bin/perl -w use strict; my ($DNS,$registrant,$admin,$tech,$billing,$domain_name,$expires); while (<>) { /^ ([\S]+)\s+[\d.]+/ and $DNS.="$1\n" and next; s/^\s+//; next unless length; m#Registrant:# .. m#\)# and chomp($registrant=$_) and ne +xt; m#Administrative Contact:# .. m#\)# and chomp($admin=$_) and ne +xt; m#Technical Contact:# .. m#\)# and chomp($tech=$_) and ne +xt; m#Billing Contact:# .. m#\)# and chomp($billing=$_) and ne +xt; /Domain Name:\s+([\w.]+)/ and $domain_name=$1 and next; /Record expires on\s+([^.]+)/ and $expires=$1 and next; } write STDOUT; format STDOUT = ====================================================================== +========== @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $domain_name Registrant: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<< $registrant Admin: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<< $admin Tech: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<< $tech Billing: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<< $billing DNS: ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<< $DNS EXPIRES: @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<< $expires .
Re: A looping and format question...
by chipmunk (Parson) on Dec 13, 2000 at 20:25 UTC
    Note that defined() is not commutative with and. defined($x and $y) is not the same as defined($x) and defined($y); they return different results when $x is '' and $y is undef. ('' and undef) returns '', which is defined.
Re: A looping and format question...
by Fastolfe (Vicar) on Dec 13, 2000 at 20:50 UTC
    All of your variables are global variables, so when they're set to $_, they will remain set. The way you have your loop designed, once you get all the way through the first set of data, those variables will retain their values, causing each iteration of the loop thereafter to call write (in other words, for every line of data afterwards, giving you an enormous number of extraneous reports).

    If you want to continue with a design like this, you should un-set your variables after you write the report. This would allow them to fill up and your defined test to check the next occurrences (assuming you fix that test up as described by other posters--it's wrong how it is now).

    I also strongly recommend you take a look at Net::WHOIS, which should make your life considerably easier.

      Thanks for the help guys...I've learned a ton with this project. The most important thing: Don't reinvent the wheel. I went witht the Whois.pm module and my format is very pretty and I'll be able to hand the info. over in time. I had one of the strong perl guys here at work patch the module for me so it gives the expiration date for the domain. He sent it off to the person who maintains that module, so that patch may be included in a later version.
      I felt like I was so close and wanted to finish it without the module's help. Didn't get me too far...Thanks again, and I've learned a few things from your feedback.
      BTW -- can anyone recommend a general programming logic book? I sure could use one.
      Matt