1

I'm working with a string containing parameters, separated by some special characters in PHP with preg_match

An example could be like this one, which has four parameters.

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

Each parameter name is followed by ?#?, and its value is right next to it, ending with ?@? (note: values can be strings or numbers, and even special characters)

I've probably overcomplicated my regex, which works in SOME cases, but not if I search for the last parameter in the string..

This example returns 2222 as the correct value (in group 1) for 2ndParm

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

but it fails if 2ndParm is the last one in the string as in the following example:

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

I'd also appreciate help in just returning one group with my result.. i havent been able to do so, but since I always get the one I'm interested in group 1, I can get it easily anyway.

3 Answers 3

2

Without 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);

demo

Sign up to request clarification or add additional context in comments.

2 Comments

Nice answer - ++.
agreed. nice and short... I became obsessed with regex, and was too focused to look elsewhere.
2

You don't need to use a regex for everything, and you should have a serious talk with whoever invented this horrid format about the fact that JSON, YAML, TOML, XML, etc exist.

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)
);

Output:

array(4) {
  ["1stparm"]=>
  string(4) "1111"
  ["2ndParm"]=>
  string(4) "2222"
  ["3rdParm"]=>
  string(4) "3333"
  ["4thparm"]=>
  string(3) "444"
}

1 Comment

the format is internally used by the scriptcase RAD. it POSTs user parameters inside a single parameter called nmgp_parms with the format shown. A very useful solution yours too.
1

You can use

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

in verbose mode, see a demo on regex101.com.


The \Q...\E construct disables the ? and # "super-powers" (no need to escape them here).
In PHP this could be

<?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";
}

?>

Which yields

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


Or shorter:

$result = array_map(
    function($x) {return array($x["key"] => $x["value"]);}, $matches);
print_r($result);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.