0

i want to extract parameter like exist in annotation

i have done this far

$str = "(action=bla,arg=2,test=15,op)";
preg_match_all('/([^\(,]+)=([^,\)]*)/', $str, $m);

$data = array_combine($m[1], $m[2]);
var_dump($data);

this gives following out put

array (size=3)
  'action' => string 'bla' (length=3)
  'arg' => string '2' (length=1)
  'test' => string '15' (length=2)

this is ignoring op (but i want it having null or empty value)

but i want to improve this so it can extract these also

  • (action='val',abc) in this case value inside single quote will assign to action
  • (action="val",abc) same as above but it also extract value between double quote
  • (action=[123,11,23]) now action action will contain array 123,11,23 (this also need to extract with or without quotation)

i don't want complete solution(if you can do it then most welcome) but i need at least first two

EDIT

(edit as per disucssion with r3mus) output should be like

array (size=3)
  'action' => string 'bla' (length=3)
  'arg' => string '2' (length=1)
  'test' => string '15' (length=2)
  'op' => NULL
Cœur
  • 37,241
  • 25
  • 195
  • 267
Bhavik Patel
  • 789
  • 6
  • 20

3 Answers3

1

Edit:

This ended up being a lot more complex than just a simple regex. It ended up looking (first pass) like this:

function validate($str)
{
    if (preg_match('/=\[(.*)\]/', $str, $m))
    {
        $newstr = preg_replace("/,/", "+", $m[1]);
        $str = preg_replace("/".$m[1]."/", $newstr, $str);
    }
    preg_match('/\((.*)\)/', $str, $m);
    $array = explode(",", $m[1]);
    $output = array();
    foreach ($array as $value)
    {
        $pair = explode("=", $value);
        if (preg_match('/\[(.*)\]/', $pair[1]))
            $pair[1] = explode("+", $pair[1]);
        $output[$pair[0]] = $pair[1];
    }
    if (!isset($output['op']))
        return $output;
    else
        return false;
}

print_r(validate("(action=[123,11,23],arg=2,test=15)"));

Old stuff that wasn't adequate:

How about:

([^\(,]+)=(\[.*\]|['"]?(\w*)['"]?)

Working example/sandbox: http://regex101.com/r/bZ8qE6

Or if you need to capture only the array within the []:

([^\(,]+)=(\[(.*)\]|['"]?(\w*)['"]?)

brandonscript
  • 68,675
  • 32
  • 163
  • 220
1

I know it's answered but you could do this which I think is what you wanted:

$str = '(action=bla,arg=2,test=15,op)';
preg_match_all('/([^=,()]+)(?:=([^,)]+))?/', $str, $m);
$data = array_combine($m[1], $m[2]);
echo '<pre>' . print_r($data, true) . '</pre>';

OUTPUTS

Array
(
    [action] => bla
    [arg] => 2
    [test] => 15
    [op] => 
)
gwillie
  • 1,893
  • 1
  • 12
  • 14
0

You can use this code:

<pre><?php
$subject = '(action=bla,arg=2,test=15,op, arg2=[1,2,3],arg3 = "to\\"t,o\\\\", '
         . 'arg4 = \'titi\',arg5=) blah=312';

$pattern = <<<'LOD'
~
(?: \(\s* | \G(?<!^) ) # a parenthesis or contiguous to a precedent match
(?<param> \w+ )
(?: \s* = \s*
     (?|  (?<value> \[ [^]]* ] )                     # array
       | "(?<value> (?> [^"\\]++ | \\{2} | \\. )* )" # double quotes
       | '(?<value> (?> [^'\\]++ | \\{2} | \\. )* )' # single quotes
       |  (?<value> [^\s,)]++ )                      # other value
     )? # the value can be empty
)?      # the parameter can have no value
\s*
(?:
    , \s*                   # a comma
  |                         # OR
    (?= (?<control> \) ) )  # followed by the closing parenthesis
)
~xs
LOD;
preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);

foreach($matches as $match) {
    printf("<br>%s\t%s", $match['param'], $match['value']);
    if (isset($match['control'])) echo '<br><br>#closing parenthesis#';
}
?></pre>
Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125