Je travaille avec une chaîne contenant des paramètres, séparés par des caractères spéciaux en PHP avec preg_match

Un exemple pourrait être comme celui-ci, qui a quatre paramètres.

1stparm?#?1111?@?2ndParm?#?2222?@?3rdParm?#?3333?@?4thparm?#?444?@?

Chaque nom de paramètre est suivi de? # ?, et sa valeur est juste à côté, se terminant par? @? (remarque: les valeurs peuvent être des chaînes ou des nombres, et même des caractères spéciaux)

J'ai probablement trop compliqué mon expression régulière, qui fonctionne dans CERTAINS cas, mais pas si je recherche le dernier paramètre de la chaîne.

Cet exemple renvoie 2222 comme valeur correcte (dans le groupe 1) pour 2ndParm

(?:.*)2ndParm\?#\?(.*?)\?@\?(?=.)(.*)

Mais il échoue si 2ndParm est le dernier de la chaîne comme dans l'exemple suivant:

1stparm?#?1111?@?2ndParm?#?2222?@?

J'apprécierais également de l'aide pour le retour d'un seul groupe avec mon résultat.

1
msks2007 8 avril 2020 à 01:54

3 réponses

Meilleure réponse

Vous pouvez utiliser

(?P<key>.+?)
\Q?#?\E
(?P<value>.+?)
\Q?@?\E

En mode verbose, consultez une démo sur regex101.com .


\Q...\E ? #
PHP
<?php
$string = "1stparm?#?1111?@?2ndParm?#?2222?@?3rdParm?#?3333?@?4thparm?#?444?@?";

$regex = "~(?P<key>.+?)\Q?#?\E(?P<value>.+?)\Q?@?\E~";

preg_match_all($regex, $string, $matches, PREG_SET_ORDER);

foreach ($matches as $match) {
    echo $match["key"] . " = " . $match["value"] . "\n";
}

?>

Qui donne

1stparm = 1111
2ndParm = 2222
3rdParm = 3333
4thparm = 444

$result = array_map(
    function($x) {return array($x["key"] => $x["value"]);}, $matches);
print_r($result);
1
Jan 7 avril 2020 à 23:16

Vous n'avez pas besoin d'utiliser une expression régulière pour tout, et vous devriez avoir une conversation sérieuse avec celui qui a inventé ce format horrible sur le fait que JSON, YAML, TOML, XML, etc. existent.

function bizarre_unserialize($in) {
    $tmp = explode('?@?', $in);
    $tmp = array_filter($tmp); // remove empty
    $tmp = array_map(
        function($a) { return explode('?#?', $a); },
        $tmp
    );
    // rearrange to key-value
    return array_combine(array_column($tmp, 0), array_column($tmp, 1));
}

$input = '1stparm?#?1111?@?2ndParm?#?2222?@?3rdParm?#?3333?@?4thparm?#?444?@?';

var_dump(
    bizarre_unserialize($input)
);

Production:

array(4) {
  ["1stparm"]=>
  string(4) "1111"
  ["2ndParm"]=>
  string(4) "2222"
  ["3rdParm"]=>
  string(4) "3333"
  ["4thparm"]=>
  string(3) "444"
}
2
Sammitch 7 avril 2020 à 23:22

Sans regex:

$str ='1stparm?#?1111?@?2ndParm?#?2222?@?3rdParm?#?3333?@?4thparm?#?444?@?';

$keyval = explode('?@?', trim($str, '?@'));

$result = [];

foreach($keyval as $item) {
    [$key, $result[$key]] = explode('?#?', $item);
}

print_r($result);

démo

2
Casimir et Hippolyte 7 avril 2020 à 23:19