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

I've been trying to solve this problem that I've been having with a conditional using RegEx. the code is as follows

while (my $curline = <IN>){ #if the current line read is a domain #domain if ($curline =~ /^#/){ print $curline, "\n"; # for debugging my $currentdomain = $curline; while($curline = <IN>){ if ($curline !~ /^#\s/ or $curline !~ /^\s/) { $server++; $currentserver = $curline; push(@serverlist, $currentserver); } ## end if elsif ($curline !~ /^\s/){ $HoA{$currentdomain} = [@serverlist]; $currentdomain = $curline; } #end else } ## end while if ( eof(IN)){$HoA{$currentdomain} = [@serverlist];} } ## end if } ## end while

Let's say I have a list domain and servers in the following format : # domain 1 servera serverb # domain 2 serverc serverb What i wanted this little piece of code to do was to have of hash of arrays with the servers assigned for each domain assigned to arrays and the domains stored into each element of the hash table with the array of servers associated with each element of the hash table. (it's 1:28 a.m and if i sound incoherent, i'm tired :) ) What actually is going on is that the first domain is actually being stored in the hashtable, however the 2nd domain is being stored in the array that's associated with the first domain. Is there a problem with my RegEx conditional? If so, where did I go wrong? Any help is greatly appreaciated. Thanks

Replies are listed 'Best First'.
Re: Quarms with RegEx
by busunsl (Vicar) on Aug 28, 2001 at 12:37 UTC
    I think the line:
    if ($curline !~ /^#\s/ or $curline !~ /^\s/)
    is wrong.

    You almost never want two negative conditions combined with 'or'.

    Try 'and' between the conditions:

    if ($curline !~ /^#\s/ and $curline !~ /^\s/)
      nice catch wise monk
      if ($curline !~ /^#\s/ or $curline !~ /^\s/)
      is logically equivalent to:
      if (1)
      because every string will either A.) not start with a '#' or B.) not start with a space.

      Might I recommend a smarter regex rather than anding two simple ones together?

      if ($curline !~ /^#?\s/)

      -Blake

        if ($curline !~ /^#?\s/)
        That will not work, because a domain line looks like:
        #domain1
        And that will not match your regex, so the condition is true, which is wrong.
      just because the phone rang while I was in the process of writing ... :)
Re: Quarms with RegEx
by chipmunk (Parson) on Aug 28, 2001 at 16:20 UTC
    One problem here is the way you've set up your two while loops. The outer loop processes one line, then the inner loop processes all the remaining lines, then the program exits. This task can be accomplished with a single loop instead. Here's one way to do it:
    my(%domains, $domain, @servers); while (<IN>) { chomp; if (s/^# *//) { if (defined $domain) { $domains{$domain} = [ @servers ]; @servers = (); } $domain = $_; } else { push @servers, $_; } } if (defined $domain) { $domains{$domain} = [ @servers ]; }
    I also chomped the newlines and removed the '# ' from before the domains.
Re: Quarms with RegEx
by stefan k (Curate) on Aug 28, 2001 at 12:45 UTC
    I haven't checked this really but what springs into my eyes is the line
    if ($curline !~ /^#\s/ or $curline !~ /^\s/)
    Shouldn't that be a and instead of an or?

    Please note that this is more a kind of intuitive debugging...

    Regards... Stefan

Re: Quarms with RegEx
by Chady (Priest) on Aug 28, 2001 at 12:50 UTC

    Something off the top of my head, and if you are sure that there is always two servers after the domain, this should work:

    { my $line = <IN>; if ($line =~ /^\#/) { my $server1 = <IN>; my $server2 = <IN>; $HoA{$line} = [$server1, $server2]; } redo unless eof(IN); }
    I'll think of something else that might help.

    Update: ok, here it is, should pass:

    my @in = <IN> { $line = shift(@in); if ($line =~ /^\#/) { my @serverlist; while ($in[0] !~ /^\#/) { my $server = shift(@in); push @serverlist, $server; } $HoA{$line} = [@serverlist]; } redo while (@in); }
    but you have to read the whole input into an array.


    He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.

    Chady | http://chady.net/
Re: Quarms with RegEx
by blakem (Monsignor) on Aug 28, 2001 at 12:33 UTC
    It doesn't sound too tricky, but I'll need a better example of your datafile in order to help you. Post a piece of it between <code> tags, and I'll take a quick look at it.

    -Blake