NekoLopez
NekoLopez

Reputation: 609

How to extract integer and decimal numbers in PHP string correctly?

I have a string in PHP where I want to extract only integer and decimal numbers, this is an example:

<?php 

$string = 'María vive en un pueblo de 25 957 habitantes y cobra 1859 euros al mes. OJO: no sé si os habéis fijado, pero los números del último ejemplo 
no llevan un punto o una coma separando los millares (25.957 o 1.859). Sé que resulta extraño, pero la nueva normativa de la R.A.E. 
dice que los números de cuatro cifras NO llevarán separación (1859) y los números de cinco cifras o más NO llevarán ni puntos ni comas, 
sino una separación (25 957 o 1 343 392). El 94% de los niños ha traído los deberes hechos. He pagado $50,95 dólares.';

?>

In this case I try to get numbers using this line:

$numbers = preg_replace('/[^0-9\.,]/', ' ', $string);

But the problem is the result is:

25 957 1859 . , 25.957 1.859 . , . . . 1859 , 25 957 1 343 392 . 94 . 50,95 .   

And I want to get this result:

25 957 1859 25.957 1.859 1859 25 957 1 343 392 94 50,95

How can I fix it?

I'd like your help.

Upvotes: 2

Views: 871

Answers (3)

tcj
tcj

Reputation: 1675

Probably not the most elegant way to do it but you could use two preg_replace functions based on your first REGEX and remove the decimals without any numbers wrapped around them like so :

$numbers = preg_replace('/[^0-9\.,]+/', ' ', $string);
$decimals = preg_replace('/([^0-9][\.,])/', '', $numbers);
var_dump($decimals); // string(56) " 25 957 1859 25.957 1.859 1859 25 957 1 343 392 94 50,95"

Live example here : https://3v4l.org/9aUCt

Upvotes: 2

Giacomo M
Giacomo M

Reputation: 4711

Use this regular expression:

(\d*\.)?\d+

NOTE
This exp will match 25 957 like 2 matches (for the space between numbers).

Upvotes: 1

rickdenhaan
rickdenhaan

Reputation: 11298

You're using a . for thousands and a , for decimals, and it looks like your text is intended for humans so there will always be a number immediately before a . and ,.

So what you want is 1 or more numbers, followed by 0 or more thousand-groups (a . followed by 3 more numbers), optionally followed by exactly one , and one or more numbers.

One or more numbers: [0-9]+
0 or more thousand-groups: (\.[0-9]{3})*
Optionally a `,` and one or more numbers: (,[0-9]+)?

Combined: [0-9]+(\.[0-9]{3})*(,[0-9]+)?

$string = 'María vive en un pueblo de 25 957 habitantes y cobra 1859 euros al mes. OJO: no sé si os habéis fijado, pero los números del último ejemplo 
no llevan un punto o una coma separando los millares (25.957 o 1.859). Sé que resulta extraño, pero la nueva normativa de la R.A.E. 
dice que los números de cuatro cifras NO llevarán separación (1859) y los números de cinco cifras o más NO llevarán ni puntos ni comas, 
sino una separación (25 957 o 1 343 392). El 94% de los niños ha traído los deberes hechos. He pagado $50,95 dólares.';

$matches = [];
preg_match_all('/[0-9]+(\.[0-9]{3})*(,[0-9]+)?/', $string, $matches);

print_r($matches[0]);

/*
Array
(
    [0] => 25
    [1] => 957
    [2] => 1859
    [3] => 25.957
    [4] => 1.859
    [5] => 1859
    [6] => 25
    [7] => 957
    [8] => 1
    [9] => 343
    [10] => 392
    [11] => 94
    [12] => 50,95
)
*/

Upvotes: 4

Related Questions