Reputation: 27689
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
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
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
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