clarkk
clarkk

Reputation: 27689

Parse and match calculation string

How do I parse and match calculation strings?

This is my code:

$pattern = '/(?:\d+(?:\.\d+)?\D)+\d+(?:\.\d+)/';
$input = [
    '1.0+2.5*5.4',
    '5*8-4'
];
foreach($input as $string){
    preg_match($pattern, $string, $match);
    print_r($match);
}

I can't figure out what I'm doing wrong.

Upvotes: 1

Views: 277

Answers (3)

mohammad mohsenipur
mohammad mohsenipur

Reputation: 3149

Try this. It works for integers and floats:

 $pattern = '/(?:\d+(?:(\.|)\d*)?\D)*\d*(?:(\.|)\d+)/';
 $input =array(
   '1.0+2.5*5.4',
   '5*8-4',
   '5*8-4string'
 );
 foreach($input as $string){
    echo "input:".$string."\n";
    preg_match($pattern, $string, $match);
    print_r("output:".$match[0]."\n");
  }

Output:

 input:1.0+2.5*5.4
 output:1.0+2.5*5.4
 input:5*8-4
 output:5*8-4
 input:5*8-4string
 output:5*8-4

Upvotes: 0

Andrew Cheong
Andrew Cheong

Reputation: 30273

The result is expected, given your expression.

Note how \D can only match once (or nonce). \D has matched the -, so nothing else can match /.

You might be tempted to solve this by putting a quantifier on larger part of your expression, but let me anticipate the problems you'll face going that way and suggest that you use a loop that substitutes a single operand-operator-operand triplet at a time, quitting when no substitutions can be made. This is because no single-pass regular expression can properly manage order of operations (e.g. PEMDAS).

Upvotes: 0

Shikiryu
Shikiryu

Reputation: 10219

It's because of the greediness of "?", try "+" as in :

$pattern = '/(?:\d+(?:\.\d+)?\D)+\d+(?:\.\d+)/';
$input = '34.27-15.44/8.44';
echo $input."\n";
preg_match($pattern, $input, $match);
print_r($match);

As for your edit:

$pattern = '/(?:\d+(?:\.?\d+)?\D)+\d+/';
$input = [
    '1.0+2.5*5.4',
    '5*8-4',
    '5*8-4string',
    'string5*8-4',
    'string'
];
foreach($input as $string){
    preg_match($pattern, $string, $match);
    print_r($match);
}

It gives:

Array
(
    [0] => 1.0+2.5*5.4
)
Array
(
    [0] => 5*8-4
)
Array
(
    [0] => 5*8-4
)
Array
(
    [0] => 5*8-4
)
Array
(
)

as I suspect you want it to.

http://codepad.viper-7.com/4FoQnB

Upvotes: 2

Related Questions