PHP: Replace rows depending regex group values?

41 views Asked by At

I have this text string:

[000] Foo
[???] Foo
[020] Foo
[???] Foo
[045] Foo
[???] Foo
[???] Foo
[110] Foo
[???] Foo

I need to check the [XXX] values for every row, but it needs to be smart:

If a ??? value is between 0** rows > replace it to 0??.

Desired result:

[000] Foo
[0??] Foo
[020] Foo
[0??] Foo
[045] Foo
[???] Foo
[???] Foo
[110] Foo
[???] Foo

Would I need preg_replace_callback()?

In a further step I want to expand it to logic "between 1XX and 2XX" etc, but I may be able to adapt that from a posted solution.

Test:

<?php

// string
$s = '[000] Foo
[???] Foo
[020] Foo
[???] Foo
[045] Foo
[???] Foo
[???] Foo
[110] Foo
[???] Foo';

// _preg_replace magic


// output
echo 'After replacement:';
echo '<pre>' . $s . '</pre>';

echo 'Desired result:';
echo '<pre>[000] Foo
[0??] Foo
[020] Foo
[0??] Foo
[045] Foo
[???] Foo
[???] Foo
[110] Foo
[???] Foo</pre>';

?>
1

There are 1 answers

0
Wiktor Stribiżew On

You may use a custom boundary based on a \G operator:

(?sm)(?:^\[0\d{2}]|\G(?!\A)).*?\R\[\K\?{3}(?=.*?\R\[0)

See the regex demo

Change 0 in ^\[0 and \R\[0 with the values you need.

Details:

  • (?sm) - DOTALL and MULTILINE modes are on
  • (?:^\[0\d{2}]|\G(?!\A)) - match either of the 2:
    • ^\[0\d{2}] - start of the line, [0, and 2 digits
    • \G(?!\A) - end of the previous successful match
  • .*?\R\[ - any 0+ chars as few as possible, up to the first line break, then the line break (\R) and a literal [
  • \K - omit all the text matched so far from match buffer
  • \?{3} - 3 ? symbols
  • (?=.*?\R\[0) - and require the presence of a line break followed with [0 after any 0+ chars, as few as possible.