tags:

views:

40

answers:

2

I want to replace all instances of an specific words between braces with something else, unless it is written between double braces, while it should show as is it was written with single braces without the filter. I have tried a code but only works for the first match. The rest are shown depending of the first one:

$foo = 'a {bar} b {{bar}} c {bar} d';
$baz = 'Chile';
preg_match_all( '/(\{?)\{(tin)\}(\}?)/i', $foo, $matches, PREG_SET_ORDER );
    if ( !empty($matches) ) {
        foreach ( (array) $matches as $match ) {
            if( empty($match[1]) && empty($match[3])) {
                $tull = str_replace( $match[0], $baz, $foo );
            } else {
                $tull = str_replace( $match[0], substr($match[0], 1, -1), $foo ) ;
            }
        }
    } 
    echo $tull;

EDIT: use case:

If I write:

"Write {{bar}} to output the template. Example: I want to go to {bar}."

I want to have:

"Write {bar} to output the template. Example: I want to go to CHILE."

+1  A: 

You can't do this in a single regex. First use

(?<!\{)\{bar\}(?!\})

to match {bar} only if there are no further braces around it. I.e.

preg_replace('/(?<!\{)\{bar\}(?!\})/m', 'CHILE', 'Write {{bar}} to output the template. Example: I want to go to {bar}.');

will return

Write {{bar}} to output the template. Example: I want to go to CHILE.

Then do a normal search-and-replace to replace {{ with { and }} with }.

Tim Pietzcker
+1  A: 

You could use two regular expressions, one to look for the double-braced items and another for the single-braced ones. Alternatively, a callback could be used to determine the replacement value with just one regular expression.

Separate patterns

$subject = 'Write {{bar}} to output the template. Example: I want to go to {bar}.';
$replacement = 'CHILE';
echo preg_replace(
    array('/(?<!\{)\{bar\}(?!\})/', '/\{\{bar\}\}/'),
    array($replacement, '{bar}'),
    $subject
);

Single pattern with callback

echo preg_replace_callback(
    '/(\{)?(\{bar\})(?(1)\})/',
    function ($match) use ($replacement) {
        if ($match[0][1] === '{') {
            return $match[2];
        }
        return $replacement;
    },
    $subject
);

Finally, are you doing this for one hard-coded labels (always bar) or will the label part be a key for some varying replacement string?

salathe
They are a series of hard coded labels, but I may add some variables later. Seems that the second pattern is a bit invalid.
peroyomas
None of the patterns are invalid, they were all tried and tested before posting up here. Since hard-coding is what you're after, the above should suffice unless there's more to the question.
salathe