Summary: Description of ParseArgs function for parsing argument lists
Prerequisites: pmwiki-2.0.0
Status: Stable
Maintainer: Petko (original author: Pm)
Discussion: ParseArgs-Talk

Questions answered by this recipe

  • Is there a function to make it easier to parse directive arguments when writing Cookbook recipes?
  • How do I make use of the ParseArgs() function?


Since 2.0.beta25, PmWiki has a built-in function called ParseArgs() that simplifies the parsing of argument strings, e.g. for (:directives:). This recipe describes how ParseArgs() works and how it can be used.

For example, here's a directive for a list of all "normal" pages in the Cookbook:

(:pagelist group=Cookbook list=normal fmt=simple:)

Or, for a search of all pages in Main containing "apple" and "cherry" but not "apple pie":

(:searchresults group=Main apple -"apple pie" cherry:)

name= usage

The potential for items to be quoted is what makes parsing such arguments a challenge. This is where ParseArgs is useful -- it will accept a string containing name=value and other (possibly quoted) arguments, and return an array with the arguments all in place. For example, given

$args = ParseArgs('group=Cookbook list=normal fmt=simple');

the $args variable would then be set with:

    $args['group']     'Cookbook'
    $args['list']      'normal'
    $args['fmt']       'simple'

This makes it simple to grab options from a string:

$args = ParseArgs($x);      // $x is the string to be parsed
$group = $args['group'];
$list = $args['list'];
$fmt = $args['fmt']; 

Default values for options can also be easily handled:

$defaults = array('fmt'=>'bygroup', 'list'=>'all');
$args = array_merge($defaults, ParseArgs($x));
$group = $args['group'];   
$list = $args['list'];     
$fmt = $args['fmt']; 

Token usage

Arguments that don't have a name= or value: in front are placed into an '' array entry:

$args = ParseArgs('group=Main apple cherry');

resulting in

    $args['group']     'Main'
    $args['']          array('apple', 'cherry');

+ and - usage

Arguments preceded by '+' or '-' get their own array entries:

$args = ParseArgs('group=Main apple -"apple pie" cherry');
    $args['group']     'Main'
    $args['']          array('apple', 'cherry')
    $args['-']         array('apple pie')

Finally, if the order of all of the arguments needs to be known, a special '#' entry provides the complete ordering:

$args = ParseArgs('group=Main apple -"apple pie" cherry');
    $args['#']         array('group', 'Main', 
                         '', 'apple', 
                         '-', 'apple pie',
                         '', 'cherry')

Quoted usage

Quoted arguments have their matched single or double quotes removed, e.g.

$args = ParseArgs('label="an example" caption=\'descriptive phrase\'');
    $args['label']     'an example
    $args['caption']   'descriptive phrase


Note that the function uses both "=" and ":" as an assignment operator. Thus, if you want to have a string like an URL that starts with "https:" in a numbered array $args[""], you need to pass a second argument to ParseArgs:

$args = ParseArgs("", '(?>(\\w+)=)');

This will return $args[""][0] = "". Otherwise, you would obtain $args['https'] = "//".


As an example, you can enter an argument string to be parsed in the box below and see the values that would result from calling ParseArgs with that string.

Key                 Value(s)
---------           --------
$arg['#']           (array) 'group' 'Main' '' 'apple' '-' 'apple pie' '' 'cherry' 
$arg['group']       'Main' 
$arg['']            (array) 'apple' 'cherry' 
$arg['-']           (array) 'apple pie' 


You can't have a parameter that has both a single and a double quote in it. (You can write "This ' is a single quote" and 'This " is a double quote', but you can't write "These '" are a single and a double quote"). In this, ParseArgs follows HTML conventions.


In this section we give more examples of calling ParseArgs to process arguments.

(Feel free to add questions or examples here.)


There's a problem when the text field contains single or double quote to be displayed:

(:gma-point lat=yyy lon=xxx text="Vincent's home":)

Here is the hack (for version 2.1.2). In the file cookbook/GoogleMapAPI/gma-2.1.2.php

 line 181 in the if structure add the following lines:
$m = preg_replace("/'/","\'", $m);
$m = preg_replace('/"/','\"', $m); 
line 304 before the call to the function parseArgs add the following lines: ->
//Hack for quotes
//end hack 

ParseArgs in PmWiki.php

function ParseArgs($x, $optpat = '(?>(\\w+)[:=])') {
  $z = array();
    $x, $terms, PREG_SET_ORDER);
  foreach($terms as $t) {
    $v = preg_replace('/^([\'"])?(.*)\\1$/', '$2', $t[3]);
    if ($t[2]) { $z['#'][] = $t[2]; $z[$t[2]] = $v; }
    else { $z['#'][] = $t[1]; $z[$t[1]][] = $v; }
    $z['#'][] = $v;
  return $z;

$x, the subject, must be a string, the optional second parameter is the pattern that is matched.

See Also


  • Pm, 2005-03-02