Different actions for different parts of a string

Any questions involving matching text strings to patterns - the pattern is called a "regular expression."

Moderator: General Moderators

Post Reply
lwc
Forum Commoner
Posts: 35
Joined: Thu Jan 11, 2007 11:04 am

Different actions for different parts of a string

Post by lwc »

How do I turn

Code: Select all

<?php
$input = "Some words.
[foobar1]some code.[/foobar1]
More words.
[foobar2]some code[/foobar2].
Other words.";
?>
to:

Code: Select all

// Output:
<b>Some words.
[foobar1]</b><i>some code.</i>[/foobar1]<b>
More words.
[foobar2]</b><i>some code</i><b>[/foobar2].
Other words.</b>;
?

i.e. one action for what's inside tags, another action for the rest of the text.
 
Thanks!

P.S.
Here's what I tried so far:
 

Code: Select all

<?php
function dosomething($string, $else = '') {
   if (empty($else))
      $string = "<b>$string</b>";
   else
      $string = "<i>$string</i>";
   return $string;
}
 
$codetag = array('\[foobar1\]', '\[foobar2\]');
$codetag_rev = array('\[\/foobar1\]', '\[\/foobar2\]');
for ($i = 0; $i < count($codetag); $i++)
  $codetag_array[] = "/([\s\S]*$codetag[$i])([\s\S]+)($codetag_rev[$i])([\s\S]*)/e";
$input_new = preg_replace($codetag_array, 'dosomething("$1") . dosomething("$2","else") .dosomething("$3") . dosomething("$4")', $input);
echo "$input\n<hr>\n$input_new";
// This becomes a huge mess and $2 doesn't get saved from being bold
echo "<hr><hr>";
// Let's try with just one tag
$input_new = preg_replace($codetag_array[0], 'dosomething("$1") . dosomething("$2","else") .dosomething("$3") . dosomething("$4")', $input);
echo "$input\n<hr>\n$input_new";
// The same thing happens
?>
MichaelR
Forum Contributor
Posts: 148
Joined: Sat Jan 03, 2009 3:27 pm

Re: Different actions for different parts of a string

Post by MichaelR »

Are you sure the output there is what you want? Doesn't really seem sensible.

If you want the output to be...

Code: Select all

<b>Some words.
[foobar1]</b><i>some code.</i><b>[/foobar1]
More words.
[foobar2]</b><i>some code</i><b>[/foobar2].
Other words.</b>
... then the code is:

Code: Select all

echo preg_replace(array('/(\[[a-z0-9]+\])(.*)(\[\/[a-z0-9]+\])/', '/^/', '/$/'), array('$1</b><i>$2</i><b>$3', '<b>', '</b>'), $input);
Or are you looking for something like BBCode, so that Bold Text[ /b] converts to <b>Bold Text</b> and Italic Text[ /i] converts to <i>Bold Text</i>? In which case the code is:

Code: Select all

echo preg_replace(array('/\[b\](.*)\[\/b\]/', '/\[i\](.*)\[\/i\]/'), array('<strong>$1</strong>', '<em>$1</em>'), $input);
lwc
Forum Commoner
Posts: 35
Joined: Thu Jan 11, 2007 11:04 am

Re: Different actions for different parts of a string

Post by lwc »

I didn't say I want [this] in general. I want just certain [this] (like foobar1 & 2).

I know it doesn't make sense with the bold example. But what I really want is to run a certain filter for everything except inside foobar1 & 2, and another filter for what is inside them.

Here's how I can implement your idea about ^ and $. However, it's only good for a preceeding/trailing tag. What if I want to filter the text (e.g. strtoupper)?

Code: Select all

<?php
function dosomething($before, $string='', $after='') {
   if (!empty($before) && !empty($after))
      $string = "$before</b><i>$string</i><b>$after";
   elseif (!empty($string))
      $string = '<b>';
   else
      $string = '</b>';
   return $string;
}
 
$codetag = array('\[foobar1\]', '\[foobar2\]');
$codetag_rev = array('\[\/foobar1\]', '\[\/foobar2\]');
for ($i = 0; $i < count($codetag); $i++)
  $codetag_array[] = "/($codetag[$i])([\s\S]+)($codetag_rev[$i])/e";
array_push($codetag_array, '/^/e', '/$/e');
$codetag_result = array('dosomething("$1", "$2", "$3")', 'dosomething("$1", "$2", "$3")', 'dosomething("$0", "before")', 'dosomething("$0")');
$input_new = preg_replace($codetag_array, $codetag_result, $input);
echo "$input\n<hr>\n$input_new";
?>
Post Reply