Re: preg_replace brain teaser
| From: | Tom Rogers | Date: | Tue, 15 Apr 2003 16:30:51 +0000 |
| Subject: | Re: preg_replace brain teaser | ||
| References: | 1 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-143978@lists.php.net to get a copy of this message | ||
Hi,
Wednesday, April 16, 2003, 12:58:38 AM, you wrote:
Ssd> Hello Everyone
Ssd> I have a slight problem with a regular expression for a preg_replace.
Ssd> I'm trying to match arguments within a string and replace them with a
Ssd> value from an array I pass to a function.
Ssd> Arguments are enclosed in curly braces.
Ssd> To make it clear here is an example:
Ssd> "The dog ate {amount} ducks for dinner and got {feel}."
Ssd> I pass the above string to a function parseArgument
Ssd> $args = array('amount'=>'four',
Ssd> 'feel'=>'sick');
Ssd> function parseArgument($string, $args)
Ssd> {
Ssd> return preg_replace('/\{([a-zA-Z0-9_-]+?)\}/e',
Ssd> '$args[\\1]', $string);
Ssd> }
Ssd> which should return the result
Ssd> "The dog ate four ducks for dinner and got sick."
Ssd> So far it works.
Ssd> Now I have the problem that opening braces have to be escaped when
Ssd> included in the text. I choose '\' as the escape character.
Ssd> So "The dog \{{amount}} ducks for dinner and got {feel}." passed to the
Ssd> above function should return
Ssd> "The dog {four} ducks for dinner and got sick."
Ssd> In order to do this I changed the pattern from "\{([a-zA-Z0-9_-]+?)\}" to
Ssd> "(?<!\\)\{([a-zA-Z0-9_-]+?)\}" which
Ssd> results in an error:
Ssd> Warning: Compilation failed: lookbehind assertion is not fixed length at
Ssd> offset 31 in d:\eclipse_21\workspace\webframework\classes\I18N.class.php
Ssd> on line 320
Ssd> First question (this is slightly off topic) I have is why is the
Ssd> lookbehind not a fixed length? It should only be one '\'. Is this a bug in
Ssd> the regex engine or am I missing something?
Ssd> Second question is there a pattern that does the job for me?
Ssd> IMPORTANT: The names in the curly brackets may only contain letters,
Ssd> digits, and '-','_' as stated in the pattern.
Ssd> I have a work around that replaces all occurences of escaped '{' with a
Ssd> differnet pattern such as %%$$%% using str_replace and after doing the
Ssd> preg_replace
Ssd> switching them back. It seems a bit clumsy! SO my goal is to do it all in
Ssd> one regex!!!
Ssd> Thanks for your help in advance
Ssd> Stefan Langer
Ssd> P.S.: Please CC me (slanger at spirit21.de) when replying since I'm on
Ssd> digest.
You might want to try preg_replace_calback() as it is quite a bit faster.
example:
$args = array('amount'=>'four', 'feel'=>'sick');
$string = "The dog ate {amount} ducks for dinner and got {feel}.";
function replace($match){
//$match[0] will be '{variable}'
//$match[1] will be 'variable'
global $args;
if(isset($args[$match[1]])) return $args[$match[1]];
else return '';
}
$new_string = preg_replace_callback('/\{(\w+)\}/','replace',$string);
(note I am not a regex guru but you should get the idea :)
--
regards,
Tom