Search code examples
phpregexpcre

Find a substring that contains increased 1s


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 1s, 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

Solution

  • You might also use (with credits to JvdV)

    ^0*\K(?:[01]*?((?(1)\1)1))+
    
    • ^ Start of string
    • 0* 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

    Regex demo | Php demo

    $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