PHP Regular Expression preg_match from array using Multine does not match all blocks

I wonder if anyone there can help me with the following regular expression, I cannot match the multine block CF.{Coordonnees Abonne}:when used in the PHP preg_match function.

Which is strange, when I make a regular expression online, it looks like it works, despite the fact that the block is in another group regex101 example

Here is the code: source code

<?php
$response = array(
      1  => 'CF.{Temps}: 1',
      2  => 'CF.{Etat}: return',
      3  => 'CF.{Code}: 2',
      4  => 'CF.{Values}: plaque',
      5  => '',
      6  => 'CF.{Coordonnees}: LA PERSONNE',
      7  => '    ',
      8  => '    10000  LA VILLE',
      9  => '    ',
      10 => '    0500235689',
      11 => '    0645788923',
      12 => '    Login : test@mail.com',
      13 => '    Password : PassWord!',
      14 => '',
      15 => 'CF.{Groupe}: 3',
      16 => 'CF.{Date}: 4',
);

print_r(parseResponseBody($response));

function parseResponseBody(array $response, $delimiter = ':')
{
    $responseArray = array();
    $lastkey = null;

    foreach ($response as $line) {
        if(preg_match('/^([a-zA-Z0-9]+|CF\.{[^}]+})' . $delimiter . '\s(.*)|([a-zA-Z0-9].*)$/', $line, $matches)) {
                $lastkey = $matches[1];
                $responseArray[$lastkey] = $matches[2];
        }
    }

    return $responseArray;
}
?>

Output:

Array
(
    [CF.{Temps}] => 1
    [CF.{Etat}] => return
    [CF.{Code}] => 2
    [CF.{Values}] => plaque
    [CF.{Coordonnees}] => LA PERSONNE
    [] => 
    [CF.{Groupe}] => 3
    [CF.{Date}] => 4
)

And there is the desired end result that I need to extract:

Array
(
    [CF.{Temps}] => 1
    [CF.{Etat}] => return
    [CF.{Code}] => 2
    [CF.{Values}] => plaque
    [CF.{Coordonnees}] => LA PERSONNE

        10000  LA VILLE

        0500235689
        0645788923
        Login : test@mail.com
        Password : PassWord!
    [CF.{Groupe}] => 3
    [CF.{Date}] => 4
)
+4
source share
3 answers

You need to check if the current value at the iteration starts in a block or not. Not at the same time:

function parseResponseBody(array $response, $delimiter = ':') {
    $array = [];
    $lastIndex = null;
    foreach ($response as $line) {
        if (preg_match('~^\s*(CF\.{[^}]*})' . $delimiter . '\s+(.*)~', $line, $matches))
            $array[$lastIndex = $matches[1]] = $matches[2];
        elseif ((bool) $line)
            $array[$lastIndex] .= PHP_EOL . $line;
    }
    return $array;
}

Live demo

+1
source

:

function parse($response, $del=':', $nl="\n") {
    $pattern = sprintf('~(CF\.{[^}]+})%s \K.*~A', preg_quote($del, '~'));
    foreach ($response as $line) {
        if ( preg_match($pattern, $line, $m) ) {
            if ( !empty($key) )
                $result[$key] = rtrim($result[$key]);
            $key = $m[1];
            $result[$key] = $m[0];
        } else {
            $result[$key] .= $nl . $line;
        }
    }
    return $result;
}

var_export(parse($response));

1 $m[1], $m[0] ( \K ). , .

+1

The regex is fine, you just need to handle the case when there is no key:

function parseResponseBody(array $response, $delimiter = ':')
{
    $responseArray = array();
    $key = null;

    foreach ($response as $line) {
        if(preg_match('/^([a-zA-Z0-9]+|CF\.{[^}]+})' . $delimiter . '\s(.*)|([a-zA-Z0-9].*)$/', $line, $matches)) {
                $key = $matches[1];
                if(empty($key)){
                    $key = $lastKey;
                    $responseArray[$key] .= PHP_EOL . $matches[3];
                }else{
                    $responseArray[$key] = $matches[2];    
                }
                $lastKey = $key;
        }
    }

    return $responseArray;
}

https://3v4l.org/rFIbk

0
source

Source: https://habr.com/ru/post/1693997/


All Articles