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

I've got what might be a naive question - but here goes: I am working on a web-based database system, and am working hard to make sure that any entries into the database are going to work - not create errors. At this point, I've taken care of all of the DB entry errors - wrong type, etc. There is one problem left: One of the things I'm doing is passing some of the data through a regex for a test. If the data in the field has some characters (like a square bracket) the script will barf (saying stuff like "unmatched brackets in regex"), and cause an ungraceful error. It's going to be quite unusual that someone does this, but I want to take care of any situation. So - what's the best way to go about this? I thought about escaping particular characters on the way in, using tr like:
$val =~ tr/\[/\\\[/g;
etc. But this seems really clunky. Other suggestions? I guess my general question is how do I exit gracefully from perl errors caused by data input?

Replies are listed 'Best First'.
(tye)Re: How to gracefully deal with a regex problem
by tye (Sage) on Mar 07, 2001 at 01:16 UTC

    Put eval { } around the part that dies and then check $@. If $@ is set, then you averted a nasty death and can refuse to put the value into the database.

    Even more reliable is:

    if( ! eval { ...; 1 } ) { warn "Invalid value ($@)..."; }

    since pathelogical cases can set $@ even though the code succeeded.

    Checking other responses, I notice \Q being suggested. Let me just add that if that works for you then you might want to consider using index() instead of a regex.

            - tye (but my friends call me "Tye")
      How would I use index() in this situation? Check for the presence of particular problematic characters?

      The regex I'm using, as I clarified above isn't really a test per se - it's a part of the script which allows users to edit their data - using the form page as a template, and replacing particular lines in the HTML code with values they entered in the first place. Maybe there are better ways to do it than the following:

      #Read in the template HTML file with the form . $form_file = $fields{formpage}; open (FILE, "$form_file"); @form = <FILE>; $select_flag=0; foreach (@form) { foreach $key (keys %fields) { if ($_ =~ /name=\"$key\"/i) { if (($key ne "table")&&($key ne "formpage")&&($key ne "dbname" +)&&($_ !~ /meta/i)) { if ($_ =~ m/check|radio/i) { $valueplace = index($_, "value="); $value = substr($_,$valueplace+7); ($value,$junk) = split(/\"/,$value); if ($fields{$key} eq $value) { $_ =~ s/input/input checked/i; print; print "\n"; $form_flag=1; last; } next; } elsif ($_ =~ /textarea/i) { #these are the regex giving me trouble if the data has wierd charact +ers $_ =~ s/><\/textarea/>$fields{$key}<\/textarea/i; } elsif ($_ =~ m/select/i) { } else { $_ =~ s/input/input value=\"$fields{$key}\"/i; } print; print "\n"; $form_flag = 1; } } elsif ($_ =~ /select/) { $select_flag=1; } elsif (($select_flag)&&($_ =~ m/option value=/i)) { $_ =~ s/option value=\"$fields{$key}\"/option value=\" +$fields{$key}\" selected/;; } } if (!$form_flag) { print; print "\n"; next; } else {$form_flag=0; next;} } }
      BTW, this script doesn't entirely work the way I'd like it to. For some reason, it can't seem to do the menu selection right. Otherwise, it works pretty well.

        Well, I wasn't thinking of the right-hand part of a regex because:

        $problem= "["; $str= "(input)"; $str =~ s/input/input value="$problem"/; print "<$str>\n"; # produces <(input value="[")>

        So I don't see how your original problem matches this problem.

        I was thinking of the fact that people surprisingly often write $str =~ /\Q$sub\E/ instead of index($str,$sub).

        Now that you give us more information, it looks to me like you need to be using CGI.pm which will know how to escape your parameter values properly.

                - tye (but my friends call me "Tye")
Re: How to gracefully deal with a regex problem
by boo_radley (Parson) on Mar 07, 2001 at 01:12 UTC
    put the regexp in a variable, then put a \Q in the regexp.
    If you need to have some unquoted thingies, use \E to demarcate the end of the \Quoting. from learnin' perl :
    /$unquoted\Q$quoted\E$unquoted/ If this doesn't seem like the right way for you, you may also want to look at quotemeta.
Re: How to gracefully deal with a regex problem
by mr.nick (Chaplain) on Mar 07, 2001 at 01:14 UTC
    I assume someplace in your code you are doing something like:
    $test=~/$var/;
    with $var containing some strange characters, to produce the error message? If so, simply quote the string $var ala:
    $test=~/\Q$var\E/;
    The quote-escape (sorry, don't know their real name) operators are extremely useful for situations like this. Check out perlop for more information.
      Turns out, this would be great if I were just doing a test - but I'm actually doing a substitution:
      $_ =~ s/input/input value=\"$fields{$key}\"/i;
      What I'm doing is creating a way for them to edit their data - so using the \Q \E makes things hard for the end user - I'm sure they'll freak out when they are faced with a field that looks like: Job\ Announcement\ for\ March... (you get the picture.)

      I realize that the eval() idea is probably the best bet.