CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
Search Posts SEARCH
Who's Online WHO'S
Log in LOG

Home: Perl Programming Help: Regular Expressions:
Using ? : inside RegExp



Sep 8, 2000, 11:21 PM

Post #1 of 4 (5236 views)
Using ? : inside RegExp Can't Post

Hello everyone,

Could someone be so kind as to help me with this? I'm working on modifying a smilies sub routine for a bulletin board, I would like for it to do the conversion to the IMG tag if and only if that image file exists, otherwise leave it untouched. Here is what I tried:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>

$avl_smilies = "smile bigsmile laugh wink mad cool rolling tongue sad cry afraid";
$test = "Testing testing :smile: testing testing :mad: testing testing :cool:";
#if I try this it will always go to the else part
$test =~ s,(\ Smile(\S+?)(\ Smile,$2 =~ $avl_smilies ? <IMG SRC=\"/graphics/ $2.gif\"> : $2,isge;
#if I try this I get:
# Testing testing IMG testing testing SRC=/graphics/.gif testing testing :cool:
$test =~ s,(\ Smile(\S+?)(\ Smile, $avl_smilies =~ $2 ? <IMG SRC=\"/graphics/$2.gif\"> : $2,isge;

It seems as if $2 is being modified but I don't know where, then I tried:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>

@avl_smilies = qw(smile bigsmile laugh wink mad cool rolling tongue sad cry afraid);
$test =~ m,(\ Smile(\S+?)(\ Smile,is;
foreach (@avl_smilies) {
if ($2 eq $_) {
$test =~ s,(\ Smile(\S+?)(\ Smile,<IMG SRC=\"/graphics/ $2.gif\" ALT=\" \">,is;

and it works as intended but does it only for the first occurrence of a smilie, and I think is very inefficient.

Also if I try:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>

$test =~ s,(\ Smile(\S+?)(\ Smile,$2 =~ $avl_smilies ? <IMG SRC=\"/graphics/ $2.gif\"> : \:$2\:,isge;</pre><HR></BLOCKQUOTE>

To leave the original value as it was, I get an error message.

I've been working on this for so many hours that I don't know what else to try, and I don't even know where the error is coming from.

Any comments and suggestions would be very appreciated.

Thanks in advance for your cooperation.

Be Well

User / Moderator

Sep 9, 2000, 4:43 AM

Post #2 of 4 (5236 views)
Re: Using ? : inside RegExp [In reply to] Can't Post

Several things ...

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>

$2 =~ $avl_smilies</pre><HR></BLOCKQUOTE>

Unless you only have one available smile, this is never going to match because the comparison is the inverse of what it should be ($avl_smilies may contain $2, but $2 won't usually contain $avl_smiles).

Even inverted, the search has problems because 'big' will actually match 'bigsmile', so you'll want to use a pattern instead and anchor it (/\b$pattern\b/).

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>

s,(\ :)(\S+?)(\ :), [..] ? <img [..]> : $2</pre><HR></BLOCKQUOTE>

... won't leave :smile: untouched, but rather change it to smile (sans :'s). You can get around that by either replacing it with ":$2:" and/or by altering your regegp to save the entirety of the original match.

It also won't catch any :smiles: at the start or the end of a string as you embed whitespace in the pattern.

The "Testing testing IMG testing testing SRC=/graphics/.gif" is actually a good trick as it appears perl is treating your everything inside <> as an array and selecting the element corresponding to match number. (ie, $array[$match_no - 1]).

I'll have to play more to see if that's a bug or a feature, but you'll want to escape the entire string for your purposes.

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">quote:</font><HR>It seems as if $2 is being modified but I don't know where<HR></BLOCKQUOTE>

See above code for the where. :-)

Everytime you do a match, you reset $1, $2, etc. so while it's available for the search, it's not available anywhere after unless you explicitly save it to $2 again with parenthesis.

Solution? Assign $2 to a temporary variable inside the substitution ...

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>

$test =~ s{(:(\S+?):)}{
my($original,$smile) = ($1,$2);
$avl_smilies =~ /\b$smile\b/
? qq(<IMG SRC="/graphics/$smile.gif"> )
: $original;

$original will be :smile:.
$smile will be smile.


[This message has been edited by Kanji (edited 09-09-2000).]

Enthusiast / Moderator

Sep 9, 2000, 6:21 AM

Post #3 of 4 (5236 views)
Re: Using ? : inside RegExp [In reply to] Can't Post

Heh, what a horrible thing for Perl to do. The main problem is you forgot to put quotes around the <IMG SRC=...> text in the regular expression.

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>

$test =~ s,(\ Smile(\S+?)(\ Smile, $avl_smilies =~ $2 ? <IMG SRC=\"/graphics/$2.gif\"> : $2,isge;

# should be

$test =~ s,(\ Smile(\S+?)(\ Smile, $avl_smilies =~ $2 ? qq[<IMG SRC="/graphics/$2.gif">] : $2,isge;

Now that you know that, your probably DYING to know why

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>

print <IMG SRC=\"/graphics/$2.gif\">;

is not a syntax error. Well <> is both the readline() operator for files, and the glob() operator for shell file-globs. Perl thinks you're using <IMG SRC...> as a file glob here, and it does something annoying in this case. Try this:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>

for $x (<what did Perl do?> ) {
print "$x ";

It prints 'what did Perl '. It doesn't print 'do?'. This is because (as far as I've seen) if Perl gets an argument to glob that isn't globbish, it just returns it. 'do?' is globbish, and matches a file that is three characters long and starts with 'do'. But the others just get returned. It's an icky 'feature' that bit you.

Anyway, I'd rewrite the code (slightly) to use a hash instead:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>

%icons = ();
@icons{qw( smile bigsmile ... )} = ();
s! Frown[^:]+):! exists $icons{lc $1} ? qq[<img src="icons/\L$1\E.jpg">] : $1!ge;

Jeff "japhy" Pinyan -- accomplished author, consultant, hacker, and teacher


Sep 9, 2000, 11:20 AM

Post #4 of 4 (5236 views)
Re: Using ? : inside RegExp [In reply to] Can't Post

Thanks a lot Kanji and Jeff for helping me understand this 'feature' of Perl, I appreciate it

Thanks for the rewrite Jeff, I'm starting to get the hang of those data structures. I just did a tiny modification to preserve the original and add alt tags:

<BLOCKQUOTE><font size="1" face="Arial,Helvetica,sans serif">code:</font><HR>

s! Frown[^:]+):! exists $avl_smilies{lc $1} ? qq[<img src="graphics/\L$1\E.gif" alt="\L$1\E">] : ":$1:"!ge;</pre><HR></BLOCKQUOTE>

Is there a way to have the else part not do anything?

Thank you both for your time and attention, I really appreciate it.

Be Well


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives