Kliver Max
Kliver Max

Reputation: 5299

When used in sscanf(), %s does not stop matching when it encounters the symbol that follows the %s

I try to parse string with php using sscanf():

$n = sscanf($line, "%s.%s.%s=%s", $ws, $layer, $perm, $role);
echo $ws." - ".$layer." - ".$perm." - ".$role."\n";

And get output:

*.*.r=* -  -  -
topp.*.a=jdbs_watcher -  -  -

Input examples:

 *.*.r=*
 topp.*.a=jdbs_watcher

What i expect to see for second string:

topp - * - a - jdbc_watcher

Why whole string has been put into $ws variable?

Upvotes: 1

Views: 1211

Answers (4)

BlitZ
BlitZ

Reputation: 12168

Well, there this behaviour was spotted before on php.net.

As a workaround, you may use this:

<?php
header('Content-Type: text/plain; charset=utf-8');

$line = 'topp.*.a=jdbs_watcher';

list($ws, $layer, $perm) = explode('.', $line);
list($perm, $role) = explode('=', $perm); 

echo $ws." - ".$layer." - ".$perm." - ".$role."\n";
?>

Result:

topp - * - a - jdbs_watcher

Upvotes: 2

srain
srain

Reputation: 9082

use ^ to avoid to be too greedy:

<?php
$line = 'topp.*.a=jdbs_watcher';
$n = sscanf($line, "%[^.].%[^.].%[^=]=%s", $ws, $layer, $perm, $role);
echo $ws." - ".$layer." - ".$perm." - ".$role."\n";

Upvotes: 3

diegoperini
diegoperini

Reputation: 1806

sscanf() is not a string parser. It is a formatted input scanner, which is used to assign formatted input into variables using C-style syntax. What you want to accomplish can be done with explode().

//Scan input
$n = sscanf($line, "%s", $input);

//Parse by .
$parsed = explode(".", $input);
//Parse by =
$parsed[2] = explode("=", $parsed[2]);

//Create bindings
$ws = $parsed[0];
$layer = $parsed[1];
$perm = $parsed[2][0];
$role = $parsed[2][1];

//Echo
echo $ws." - ".$layer." - ".$perm." - ".$role."\n";

Upvotes: 2

Paul
Paul

Reputation: 141829

%s will match as many characters as it can before a whitespace delimiter. You could get something similar working with preg_match instead:

preg_match("/(.*)\.(.*)\.(.*)=(.*)/", $line, $matches);
array_shift($matches);
list($ws, $layer, $perm, $role) = $matches;

Demo

Upvotes: 3

Related Questions