5

I would like to find a pattern {text} and replace text including curly braces.

$data = 'you will have a {text and text} in such a format to do {code and code}';
$data= preg_replace_callback('/(?<={{)[^}]*(?=}})/', array($this, 'special_functions'),$data);

and my special function contain the callback code to replace the braces and completely and text conditionally.

public function special_functions($occurances){
        $replace_html = '';
        if($occurances){
            switch ($occurances[0]) {
                case 'text and text':
                    $replace_html = 'NOTEPAD';
                    break;
                case 'code and code':
                    $replace_html = 'PHP';
                    break;

                default:
                    $replace_html ='';
                    break;
            }
        }
        return $replace_html;
    }

Expected Output

you will have a NOTEPAD in such a format to do PHP

How can i replace text and curly braces at the same time using preg_replace_callback in php using regex

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
Shadow
  • 141
  • 1
  • 7

2 Answers2

3

You need to edit the pattern like this:

$data = preg_replace_callback('/{{([^{}]*)}}/', array($this, 'special_functions'), $data);

The {{([^{}]*)}} pattern will match:

  • {{ - {{ substring
  • ([^{}]*) - Group 1: any 0+ chars other than { and }
  • }} - a }} text

Then, inside the special_functions function, replace switch ($occurances[0]) with switch ($occurances[1]). The $occurrances[1] is the text part captured with the ([^{}]*) pattern. Since the whole match is {{...}} and the captured is ..., the ... is used to check the possible cases in the switch block, and the braces will get removed since they were consumed (=added to the match value that is replaced as a result of the preg_replace_callback function).

See the PHP demo.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • That works. I have a doubt. $occurances[0] contain text with braces and $occurances[1] contain text without braces. So logically $occurances[0] should replace both text and braces ? – Shadow Oct 05 '18 at 07:49
  • @Shadow `$occurances[0]` does not replace anything. That is the text matched with `preg_replace_callback` function and hence it is the text that will be replaced. – Wiktor Stribiżew Oct 05 '18 at 07:51
  • I have upvoted. Also always what is in [1] index will be replaced. is that right ? – Shadow Oct 05 '18 at 08:01
  • @Shadow Since `$occurrances[1]` is a part of `$occurrances[0]`, of course it will be replaced. `preg_replace_callback` searches for all non-overlapping matches, and replaces them with defined replacements. – Wiktor Stribiżew Oct 05 '18 at 08:05
  • So what ever the text inside curly braces the above answer works fine under all conditions ? – Shadow Oct 05 '18 at 08:12
  • 1
    @Shadow Yes, but the `[^{}]*` prevents any match when the text inside `{{...}}` contains `{` or `}`. If you need them, replace `[^{}]*` with `.*?`. – Wiktor Stribiżew Oct 05 '18 at 08:14
  • Just for clarification i noticed a typo in my question that contain regex for double curly braces but my string contain only single curly braces string. – Shadow Oct 05 '18 at 09:22
  • 1
    @Shadow Ok, that is not that important, remove one `{` and `}` from the pattern, `'/{([^{}]*)}/'`, definitely, no rocket science :) – Wiktor Stribiżew Oct 05 '18 at 09:27
  • if i want to find string starting with braces and a constant text should i change to `/{{MyText([^{}]*)}}/` or `/{{([^{MyText}]*)}}/` – Shadow Oct 09 '18 at 05:00
  • @Shadow Look, `[^{}]` matches any single char other than `{` and `}`. Now, do you think `[^{MyText}]` makes sense? – Wiktor Stribiżew Oct 09 '18 at 06:55
  • got it. Thank you – Shadow Oct 11 '18 at 04:58
  • Sorry for bothering you again. I would like to replace curly braces with sqaure. I changes the code and didn't work. Can you please help. – Shadow Oct 17 '18 at 11:17
  • @Shadow Please share your non-working code via https://3v4l.org or http://ideone.com – Wiktor Stribiżew Oct 17 '18 at 11:30
  • want to change `/{addon=>([^{}]*)}/` to `/\[addon=>([^[\]]*)\]/` so as to accept text inside square bracket. In `regex101` it only matches first occurance – Shadow Oct 17 '18 at 11:34
  • @Shadow Well, that is obscure. Do you want to match a string like `[addon=>text here!]`? Use `/\[addon=>([^][]*)]/`. See [this regex demo](https://regex101.com/r/2sOokN/2). – Wiktor Stribiżew Oct 17 '18 at 11:51
0

If you have such a complicated regexp, you might want to look at T-Regx:

$data = 'you will have a {text and text} in such a format to do {code and code}';

pattern('{{([^{}]*)}}')
  ->replace($data)
  ->first()
  ->callback(function (Match $match) {
      switch ($match->group(1)) {
          case 'text and text':
              return 'NOTEPAD';

          case 'code and code':
              return 'PHP';

          default:
              return '';
      }
  });
Danon
  • 2,771
  • 27
  • 37