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

I have a chatterbox script that let's the admin add custom emoticons to the system and am having problems getting the s/// to work.

The FACE can be ANYTHING pretty much. It can be a word, a series of letters and numbers, some characters like *help* or <help> or pretty much anything. The only thing that's required is the FACE be separated by a space on each side so it doesn't subsitute things like "face" in the word "preface".

id is just a number name is the name the called it (ie: SmileyFace) location is the URL of the image of the name face is the code to s/// if it is found (ie: :) , :( , *hug* ) Right now it's not s/// anything and just spits back the whatever you put in. If you type in "Hello there! :) " it prints it back instead of the emoticon.

Any ideas what I goofed?

I removed \b as suggested in the room but that didn't change the output. I tried removing \Q and \E but it errored out due to a quantifier problem since I have an emoticon face *crying*. THE SCRIPT: this is a basic chatterbox script, much like PM has, that let's people post messages to the site with each other.

####### # connecting to the DB again so we can filter emoticons ####### my $data = qq(SELECT id, name, location, face FROM emoticons); my $sth = $dbh->prepare($data); $sth->execute() or die $dbh->errstr; my ($id, $name, $location, $face); $sth->bind_columns(\$id, \$name, \$location, \$face); foreach my $line (reverse @keep) { my ($username, $message, $date, $ip) = split(/<!!>/, $line); while ($sth->fetch) { $message =~ s|\b\Q$face\E\b| <img src="$location" alt="$name"> | +gi; } if ($message =~ m|^/me|i) { $message =~ s|^/me||i; print qq(<b><i><a href="#" TITLE="Message sent on $date by $ip"> +$username</a></i></b> <i>$message</i><br>); } else { print qq(<b><a href="#" TITLE="Message sent on $date by $ip">$us +ername</a>:</b> $message<br>); } }


"Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

sulfericacid

Replies are listed 'Best First'.
Re: substitutions with unknown data (\b is \w not \s)
by tye (Sage) on Mar 28, 2005 at 19:58 UTC

    \b finds boundaries between \w and \W characters. What you want instead is:

    /(?<!\S)\Q$face\E(?!\S)/

    which means that the face can't be preceeded by a non-space characters [like (?<=\s) except it allows $face to appear at the front of the message] and can't be followed by a non-space characters [like (?=\s|$)].

    - tye        

      Thanks for that code. I inserted it but I'm still having the same problem. I'll keep using it though since it's definitely better than what I was using.

      I insterted a little test to do a printout of the faces to make sure we are using the right data.

      I added

      my ($username, $message, $date, $ip) = split(/<!!>/, $line); while ($sth->fetch) { $message =~ s|(?<!\S)\Q$face\E(?!\S)| <img src="$location" alt=" +$name"> |gi; print "$face<br>"; }
      And the output was
      *Crying* :) :( :P :O *hug* *flower* ;) *evil* *love* *yawn* 0<- albie *thumb* *angel* *cool* pix action test test: oh pix: emoticon :) test pix: emoticon :) test test: *hug* test: *hug* test: *hug* test: *hug* test: test :) here *hug* test test: test :) here *hug* test
      So the $face data IS right but it's still not doing any of the s/// in the data. Any other suggesitons?

      Thanks.



      "Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

      sulfericacid

        This wouldn't show if you had spaces in your "face" strings, for example.

        For a situation like this, I'd probably just use "perl -d", set a break point at the loop and use "x $message" and "x $face" a couple of times.

        But you can also use something like Data::Dumper to get some more precise information about your data.

        - tye        

Re: substitutions with unknown data
by Roy Johnson (Monsignor) on Mar 28, 2005 at 19:59 UTC
    You don't want the \b, you want to match whitespace or start/end of string.
    $message =~ s|(?:^|\s)\Q$face\E(?:$|\s)| <img src="$location" alt="$na +me"> |gi;

    Caution: Contents may have been coded under pressure.
Re: substitutions with unknown data
by tlm (Prior) on Mar 28, 2005 at 23:14 UTC

    I think what's happening is that you're exhausting your $sth->fetch on the first input line, so that in subsequent lines, the while ($sth->fetch) loop doesn't even execute. What I think you have to do is slurp all your DB records into some array @emoticons (or whatever you perfer), and then replace the while ($sth->fetch) with

    for my $emoticon (@emoticons) { my ($id, $name, $location, $face) = @$emoticon; # do your substitution, with the fixes already given # to you in other comments }

    the lowliest monk