'PHP: Cannot get regex pattern to repeat [duplicate]

I have an input string that looks something like this:

$txt = '!1 aaa !2 bb bb !5 cc cc cc !4 dd';

In other words, I have a number of fields, each starting with an exclamation mark and a digit.

It want to turn this into something like this:

<div class="x1">aaa</div>
<div class="x2">bb bb</div>
<div class="x5">cc cc cc</div>
<div class="x4">dd</div>

where the div class derives from the digit following the exclamation mark in the input string.

I've tried this PHP command:

preg_replace("/!([0-9]) (.*) !/U", "<div class=\"x\\1\">\\2</div>\n!", $txt)

But that produces this output:

<div class="x1">aaa</div>
!2 bb bb <div class="x5">cc cc cc</div>
!4 dd

It's obvious that the last field (!4 dd) is not matched, since it doesn't have a final !. And I assume that the second field (!2 bb bb) is not matched because its initial ! actually comes from the replacement of the first string.

So, I guess I know why it isn't working, but I can't work out how to do this correctly.



Solution 1:[1]

You can use

echo preg_replace('~!(\d+)\s*(.*?)\s*(?=!\d|$)~s', "<div class=\"x\$1\">\$2</div>\n", $txt);

See the regex demo and the PHP demo. Details:

  • ! - a ! char
  • (\d+) - Group 1: one or more digits
  • \s* - zero or more whitespaces
  • (.*?) - Group 2: any zero or more chars as few as possible
  • \s* - zero or more whitespaces
  • (?=!\d|$) - a positive lookahead that matches a location that is immediately followed with a ! + digit or end of string.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1