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

I am working on an IRC bot for scractch. I am having problem's fine tuning the commands that are passed to it.
if($_ =~ /^:(.*)!(.*) PRIVMSG $channel :(.*)$/){ my $user = $1; my $host = $2; my $message = $3; if($message =~ /^!quit$/){ die "Quiting!\n"; } }
$_ is comming from the socket. The user, host and message do get parsed out correctly, but when it comes to the commands, !quit for an example, it will only work if I broaden the regex by removeing the carrot and the scalar, ^ and $. The striing being parsed looks exactly like:
:Admin!Admin@leet-A0B340B0.host.com PRIVMSG #channel :!quit
Is $message being giving some unseen values from $3 that would not allow the !quit command from working when it is fine tuned with ^ and $? If it it is not fine tuned, !quit could appear anywhere in the message and work, which is not good :) Thanks for any ideas and help.

Retitled by davido.

Replies are listed 'Best First'.
Re: Regexp problem matching commands for IRC bot
by ikegami (Patriarch) on Dec 17, 2004 at 20:44 UTC

    1) They're called "carets". They're not edible.

    2) "it will only work if I broaden the regex by removeing the carrot and the scalar" Not so:

    $_ = ':Admin!Admin@leet-A0B340B0.host.com PRIVMSG #channel :!quit'; $channel = '#channel'; if($_ =~ /^:(.*)!(.*) PRIVMSG $channel :(.*)$/){ my $user = $1; my $host = $2; my $message = $3; if ($message =~ /^!quit$/){ die "Quiting!\n"; } } __END__ output ====== Quiting!

    $_ is apparently not what you expect it to be.

    3) Why use a regexp for to compare against a constant string?
    $message =~ /^!quit$/
    is not as good as
    $message eq '!quit'

    4) I bet
    /^:(.*)!(.*) PRIVMSG (#\S+) :(.*)$/
    is not as efficient as:
    /^:([^!]*)!(\S*) PRIVMSG (#\S+) :(.*)$/

    5) Why use $channel in the regexp? That's rather odd. I'd use:

    if($_ =~ /^:([^!]*)!(\S*) PRIVMSG (#\S+) :(.*)$/){ my $user = $1; my $host = $2; my $chnl = $3; my $message = $4; if ($chnl eq $channel) { if ($message =~ /^!quit$/){ die "Quiting!\n"; } ... } }
Re: Regexp problem matching commands for IRC bot
by friedo (Prior) on Dec 17, 2004 at 20:09 UTC
    The problem is that you are using greedy-capture in your regex. ( (.*) ). This will capture as much as possible up to !, so when a message begins with !, $1 ends up containing everything on the line until that point. You can solve this easily by using non-greedy capture. ( (.*?) ).

    However, I do wonder why you're doing this completely from scratch, when there are several IRC interfaces available on CPAN.

      That shouldn't be the problem. Yes, it'll try that first, but in order to match the PRIVMSG part, it'll have to back off. My guess would be that it's something like CRLF issues. The best bet to debug it would be to look at exactly what's held in $message, checking for any characters you weren't expecting (trailing spaces? Trailing carriage return? etc), and possibly match against just /^!quit/ or /^!quit\b/, or maybe /^!quit\s*$/. But the advice to use an existing IRC framework like Net::IRC is good.
        Yeah, I also forgot to explain that if you just use the ^ in the regex it does not work, not does just using $, so there might be something in front and back of !quit in $message.
      Do you have an example of a better regex to use? I am doing it from scratch because I think it is easier for me to implement my functions, like a Google/Yahoo search. Also it is a good challenge :)
Re: Regexp problem matching commands for IRC bot
by Forsaken (Friar) on Dec 21, 2004 at 15:33 UTC
    why make life more difficult than strictly necessary? just run a split over the whole line, using whitespace as the divider. that way you can simply compare $event[2] to '!quit', makes things a lot easier to deal with, especially as the bot gets more complex. drop me a line if you have more questions, i've spent more time tinkering with perl irc bots than i care to admit ;-)