Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Regex for the regex lovers!

Status
Not open for further replies.

spyderco

Programmer
Jan 23, 2005
107
US
I have a chatterbox and I want to add color codes to the messages.

Code:
  [red] Hi there [/red]
  [orange] yep [/orange]

And it would parse in the real HTMl font color tags. I actually have this working with the following regex.

Code:
$line =~ s/\[$cname\](.+?)\[\/$cname$\]/<font color="$ccolor">$1<\/font>/gi;

There is a problem though. It produces icky HTML when there are nested cname tags.

Code:
   [purple] test [orange] text [/orange] [/purple]

becomes
   <font color="purple"> test <font color="orange"> test </font> </font>

The regex needs to s/// only codes that ARE NOT nested. I am not sure what to do with the following if it happens. Perhaps ignore the s/// altogether? I think that would be best.

Code:
   [yellow] Hi [blue] there [/yellow] [/blue]

Last but not least, I think this is the hard part. I am going over each $name from an array. How would this factor into the regex knowing which are nested tags and which aren't if it can't do them all at the same time?

Code:
foreach my $line (@keep)  # @keep holds all messages
{
   foreach my $color (@colors) # colors holds the color codes
   {
      my ($cname, $ccolor) = split(/<!!>/, $color);
      $line =~ s/\[$cname\](.+?)\[\/$cname$\]/<font color="$ccolor">$1<\/font>/gi;
   }
}
 
you should try just transforming the tags, and not capturing the text between the tags. I would be tempted to hard code all the tags you wish to allow your users to be able to post:

Code:
foreach my $line (@keep) {  # @keep holds all messages
   $line =~ s/\[COLOR=(.+?)\]/<span style="color:$1">/gi;
   $line =~ s/\[/color\]/<\/span>/gi; 
   $line =- s/\[b\]/<b>/gi;
   $line =~ s/\[\/b]/<\/b>/gi;
   etc
   etc
   etc
}
 
I would do that except the colors to s/// are actually a dynamic configuration. The admin can add/remove colors from the MySQL db as they please so there's really no way to go about this method, unfortunately.
 
then use a hash table for the colors. And why limit the colors? Just a hassle for the admins....

Code:
my %colors = (
   red => 'red',
   blue => 'blue',
   green => 'green'
);	

my @keep = ([ignore]
'[COLOR=red]test [b]red[/b][/color]',
'test [COLOR=blue]test blue[/color]',
'test [COLOR=purple]test purple[/color]'[/ignore]
);

foreach my $line (@keep) {  # @keep holds all messages
   $line =~ s/\[COLOR=(.+?)\]/exists($colors{$1}) ? "<span style=\"color:$colors{$1}\">" : "<span style=\"color:black\">" /egi;
   $line =~ s/\[\/color\]/<\/span>/gi;
   $line =~ s/\[b\]/<b>/gi;
   $line =~ s/\[\/b]/<\/b>/gi;
   print "$line<br/>";
}
 
can't you just get away with this?

... or have i lost the plot???

(i am afraid i cannot work out how to stop the colors rendering in the __DATA__ section below)

Code:
[b]#!/usr/bin/perl[/b]

@keep = <DATA>;

@colors = qw( orange red green yellow blue );

foreach my $line (@keep)
{
   foreach my $color (@colors)
   {
      $line =~ s|\[$color\]|<font color=$color>|g;
      $line =~ s|\[/$color\]|</font>|g;
   }
   print $line;
}

[blue]__DATA__
blah blah blah [orange] yep [/orange] blah blah
blah blah blah [red] yep [green] nope [/green] [/red] blah blah
blah blah blah [green] yep [/green] blah blah
blah blah blah [red] yep [green] nope [yellow] maybe [/yellow] [/green] [/red] blah blah
blah blah blah [blue] yep [green] nope [/green] [/blue] blah blah[/blue]


Kind Regards
Duncan
 
that's basically what I have suggested but with a hash instead of an array so you avoid the looping through the @colors array over and over. Use the ignore tags to display TGML tags, it's in the TGML tags instructions.
 
Hi Kevin

Magnificent regex - just can't grasp why the OP posted:

[orange] yep [/orange]

and you have used:

[ignore]test red[/ignore]

I am tired - and probably not noticing something. If this is the case i apologise!


Kind Regards
Duncan
 
here it is literally spelled out :

[ignore]
[ignore]some red text[/ignore][/ignore]

will display:

[ignore]
some red text[/ignore]

you can wrap ignore tags around multiple lines of code just like code tags and other tags.
 
i think i had better get some sleep!

i still can't grasp why the word color is inside the square braces?

the OP didn't use the word color at all?

by the way - your regex is by far the best way to tackle the multi-colour situation. Nice!


Kind Regards
Duncan
 
Oh, I used color, it really doesn't have to be there, just seemed to make sense to me when I was writing the code down.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top