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

This is probably something blindingly simple but I have been knocking myself out for about a day now. Adding some functioning to old code and now a subroutine that validates a user id will not work correctly.

This is the existing code, works fine.

sub validate_owner{ my ($str) = @_; print "Owner is $str in sub_validate_owner\n" if ($debug); # Remove leading and trailing whitespace. $str =~ s{\A \* | \s* \z}{}gxm; if ($str =~ /nbk[A-z0-9]{4}/ or /nbd[A-z0-9]{4}/ or /root/){ print "Error $str is not a valid job owner\n"; $error = 1; return 1; } else { #No match for string. return; } } my $owner = get_jobname $_; print "Owner line is $owner\n" if ($debug); # Split id@hostname and get the id value. $owner = (split /@/,$owner)[0]; print "Owner ID is $owner\n" if ($debug); validate_owner($owner);

New code that doesn't work. No change to the sub, just that the value is coming from a hash. The sub will find the first match, but not the nbs or root match in the regex.

sub validate_owner{ my ($str) = @_; print "Owner is $str in sub_validate_owner\n" if ($debug); # Remove leading and trailing whitespace. $str =~ s{\A \* | \s* \z}{}gxm; if ($str =~ /nbk[A-z0-9]{4}/ or /nbd[A-z0-9]{4}/ or /root/){ print "Error $str is not a valid job owner\n"; $error = 1; return 1; } else { #No match for string. return; } } if (defined $jobs{'owner'}){ my $owner = $jobs{'owner'}; # Split id@hostname and get the id value. $owner = (split /@/,$owner)[0]; print "Owner ID is $owner\n" if ($debug); validate_owner($owner); }

Now for the fun part. If you change the subroutine to this, it works

sub validate_owner{ my ($str) = @_; print "Owner is $str in sub_validate_owner\n" if ($debug); # Remove leading and trailing whitespace. $str =~ s{\A \* | \s* \z}{}gxm; print "Owner is $str in sub_validate_owner\n" if ($debug); # if ($str =~ /nbk[A-z0-9]{4}/){ print "Error $str is not a valid job owner\n"; $error = 1; return 1; } if ($str =~ /nbd[A-z0-9]{4}/){ print "Error $str is not a valid job owner\n"; $error = 1; return 1; } if ($str =~ /root/){ print "Error $str is not a valid job owner\n"; $error = 1; return 1; }

Replies are listed 'Best First'.
Re: Not matching REGEX
by FunkyMonk (Bishop) on Aug 30, 2007 at 18:04 UTC
    This
    if ($str =~ /nbk[A-z0-9]{4}/ or /nbd[A-z0-9]{4}/ or /root/){

    is the same as

    if ($str =~ /nbk[A-z0-9]{4}/ or $_ =~ /nbd[A-z0-9]{4}/ or $_ =~ / +root/){

    which not what I think you're after. Perhaps you meant

    if ($str =~ /nbk[A-z0-9]{4}/ or $str =~ /nbd[A-z0-9]{4}/ or $str +=~ /root/){

      That was it. In the legacy code the $_ held the owner value, so it worked there. Thanks a bunch.
Re: Not matching REGEX
by ikegami (Patriarch) on Aug 30, 2007 at 18:48 UTC
    By the way, /root/ means "contains 'root'", not "is 'root'". You'll get an undesired error if the user is astrootter. /root/ should be /^root\z/. The same problem exists in the other regexps too.
Re: Not matching REGEX
by suaveant (Parson) on Aug 30, 2007 at 18:17 UTC
    FunkyMonk points out the problem, I'll point out a minor improvement...

    You can actually put those all together in one RegEx like so

    $str =~ /nb[dk][A-z0-9]{4}|root/;
    Which should be quite a bit more efficient than 3 regexes.

                    - Ant
                    - Some of my best work - (1 2 3)

      Thanks. I'm just happy I got the hash of hashs to work that triggered this problem. Now a improved REGEX, whee.
Re: Not matching REGEX
by jwkrahn (Abbot) on Aug 30, 2007 at 20:35 UTC
    # Remove leading and trailing whitespace. $str =~ s{\A \* | \s* \z}{}gxm;

    That doesn't actually remove leading whitespace, it removes a leading   *   character. You probably want s{\A \s+ | \s+ \z}{}gx instead.

    if ($str =~ /nbk[A-z0-9]{4}/ or /nbd[A-z0-9]{4}/ or /root/){

    The character class [A-z0-9] also matches the characters   [ \ ] ^ _ `    Did you intend to include those characters or did you really mean to use [A-Za-z0-9]?