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

Hi Monks,

I'm trying to trigger an error message if non-alphanumeric characters (excluding spaces) are matched. In other words, strings such as 'asdfad', 'a big apple', '7perl m6onks' should be accepted but not 'asd:fad' or 'a big %apple'. The following code seems to work but is there a better way?
if ($string =~ /[^a-zA-Z1-9 ]/) { # trigger error message }

Replies are listed 'Best First'.
Re: Match alphamumeric and space
by Zaxo (Archbishop) on Nov 17, 2002 at 03:20 UTC

    That is hard to improve on. You may like to give it a meaningful name and precompile it:

    my $ungood = qr/[^a-zA-Z1-9 ]/; warn "Bad Text!" if $string =~ $ungood;
    If you want to count tabs and newlines as spaces, you can use the \s character class instead of your space, and add the s qualifier to the regex.

    It could be worthwhile someday to recast your character class as unicode, something like $ungood = qr/[\P(IsAlnum)\P(IsSpace)]/s; $ungood = qr/[^\p(IsAlnum)\p(IsSpace)]/s; (Oops!).

    After Compline,
    Zaxo

Re: Match alphamumeric and space
by diotalevi (Canon) on Nov 17, 2002 at 03:10 UTC

    No you've got it right. I'd use POSIX character classes but that's because I'm thinking ahead to perl6 and Unicode. It's just a good habit to get into. Your equivalent regex would look like m{[^[:alnum:] ]}. If you mean whitespace in general as opposed to just the literal ' ' character then use \s or :space:.

    __SIG__ use B; printf "You are here %08x\n", unpack "L!", unpack "P4", pack "L!", B::svref_2object(sub{})->OUTSIDE;
Re: Match alphamumeric and space
by sauoq (Abbot) on Nov 17, 2002 at 04:25 UTC

    You left '0' out of your character class. Other than that it's fine. It would have been harder to leave out if you used [:alnum:] or even \d in your char class.

    More a matter of completeness than an actual suggestion, you should know that tr/// can also be used for this. The /c modifier can be used to complement the search list. tr/// is sometimes faster than a regex.

    This is equivalent to your example. (Well, almost. I allow '0' too.)

    if ($string =~ tr/a-zA-Z0-9 //c) { # trigger error message. }

    If you need to allow newlines and tabs, you can do that too.

    if ($string =~ tr/a-zA-Z0-9 \t\n//c) { # trigger error message. }

    Character classes like \d or [[:alpha:]] won't work with tr/// though.

    -sauoq
    "My two cents aren't worth a dime.";