I have a string only made by 0
and 1
, and I need to find a sub string that starts with one 1
, and ends with another cascade of 1
s, each match of 1
the consecutive 1
increases by one.
For example, 0101101011101
would catch 1011010111.
I tried
(?:(1(?(1)\1)).*?)+
but it doesn't work.
input | groups | output |
---|---|---|
01 |
0[(1)] |
1 |
1001111 |
[(1)00(11)]11 |
10011 |
010011111 |
0[(1)00(11)(111)] |
10011111 |
0100111110001110 |
0[(1)00(11)(111)]0001110 |
10011111 |
0100111011001110 |
0[(1)00(11)101100(111)]0 |
10011101100111 |
0100111110011110 |
0[(1)00(11)(111)00(1111)]0 |
10011111001111 |
You might also use (with credits to JvdV)
^0*\K(?:[01]*?((?(1)\1)1))+
^
Start of string0*
Match optional zeroes\K
Clean the current match buffer(?:
Non capture group to repeat as a whole
[01]*?
Match optional 0
or 1
as least as possible(
Capture group 1
(?(1)\1)1
If clause, if where is group 1, match what we already have and add a 1
)
Close group 1)+
Close non capture group and repeat 1+ times$strings = [
"01",
"1001111",
"010011111",
"0100111110001110",
"0100111011001110",
"0100111110011110",
"0100111111111111110001110",
"0100111011001110",
"1011010111",
"0100111011001110",
];
$pattern = '/^0*\K(?:[01]*?((?(1)\1)1))+/m';
foreach ($strings as $s) {
if (preg_match($pattern, $s, $match)) {
echo "$s --> " . $match[0] . PHP_EOL;
}
}
Output
01 --> 1
1001111 --> 10011
010011111 --> 10011111
0100111110001110 --> 10011111
0100111011001110 --> 10011101100111
0100111110011110 --> 10011111001111
0100111111111111110001110 --> 10011111111111111
0100111011001110 --> 10011101100111
1011010111 --> 1011010111
0100111011001110 --> 10011101100111