3

Consider this text

$text = 'bla bla bla bla (=abc) bla bla bla bla (=var.var)';

There are 2 special values there (=abc) and (=var.var)

I need to replace them with values from this array:

$array['abc']='word1';
$array['var.var']='word2';

Basically inside the pattern is (=[a-z.]+) (chars a-z and dot).

Result i need: bla bla bla bla *word1* bla bla bla bla *word2* (without *)

I tried this with no luck

preg_replace('/\(=([a-z\.]+)\)/',"$array['\\1']",$text);

Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in D:\net\test\index.php on line 9

2 Answers2

3

Since you the replacement string cannot be derived from the contents of the match (it involves external data in $array, you need to use preg_replace_callback.

This example assumes PHP 5.3 for anonymous functions, but you can do the same (in a slightly more cumbersome way) with create_function in any PHP version.

$text = 'bla bla bla bla (=abc) bla bla bla bla (=var.var)';
$array['abc']='word1';
$array['var.var']='word2';

$result = preg_replace_callback(
            '/\(=([a-z\.]+)\)/', 
            function($matches) use($array) { return $array[$matches[1]]; },
            $text);
Jon
  • 396,160
  • 71
  • 697
  • 768
  • oh crap. first time i see `use(arg)` what's that O_O – dynamic Mar 20 '11 at 14:07
  • @yes123: Re `use($arg)`: the variable `$arg` (which must be in scope) becomes available to use inside the anonymous function as well -- otherwise you couldn't access it. – Jon Mar 20 '11 at 14:09
  • @jon: isn't that equal to `global $arg;` inside the func? Anyway i use php 5.3 so it's fine – dynamic Mar 20 '11 at 14:13
  • @yes123: If `$arg` is already a global, it is. But `use` will also work if all this code were inside a function and `$array` was a local variable. – Jon Mar 20 '11 at 14:14
  • What do you mean? in this case wasn't this equal? `function($matches) {global $array; return $array[$matches[1]]; }` – dynamic Mar 20 '11 at 14:19
  • @yes123: I don't think I can explain it any better. Globals are generally undesirable; `use` allows you to avoid them. If you don't mind having a global, then `use` doesn't offer you anything. – Jon Mar 20 '11 at 14:24
  • Hm, maybe i gotcha, generally is better to avoid `global` by using `use()` (if i got that right, tho I don't get why) – dynamic Mar 20 '11 at 14:42
  • @yes123: Have a look at this question as well: http://stackoverflow.com/questions/1557787/are-global-variables-in-php-considered-bad-practice – Jon Mar 20 '11 at 14:45
  • in the answer the author doesn't seem to advise against global – dynamic Mar 20 '11 at 14:48
  • @yes123: Read also the first comment below the answer ;) – Jon Mar 20 '11 at 15:01
  • ye, as the OP I use global too and i don't see nothing strange with it xD (I use to globalize my variable that contains all the current config) – dynamic Mar 20 '11 at 16:31
2

The < PHP 5.3 solution :)

$text = 'bla bla bla bla (=abc) bla bla bla bla (=var.var)';

$text = preg_replace_callback('/\(=([\w.]+?)\)/', 'processMatches', $text);

function processMatches($matches) {
    $array = array();
    $array['abc']='word1';
    $array['var.var']='word2';
    return isset($array[$matches[1]]) ? $array[$matches[1]] : '';
}

var_dump($text); // string(43) "bla bla bla bla word1 bla bla bla bla word2"

CodePad.

alex
  • 438,662
  • 188
  • 837
  • 957
  • This is a fully correct solution as well, but it's not ideal because you must either define `$array` inside `processMatches`, or make it a global. But +1 for the `isset` test. – Jon Mar 20 '11 at 14:12
  • @Jon Thanks, it is a shame the matches need to scoped to the callback. – alex Mar 20 '11 at 14:13