396

I want to extract the digits from a string that contains numbers and letters like:

"In My Cart : 11 items"

I want to extract the number 11.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Bizboss
  • 7,792
  • 27
  • 109
  • 174

23 Answers23

634

If you just want to filter everything other than the numbers out, the easiest is to use filter_var:

$str = 'In My Cart : 11 items';
$int = (int) filter_var($str, FILTER_SANITIZE_NUMBER_INT);
Daniel Bøndergaard
  • 6,373
  • 1
  • 12
  • 3
406
$str = 'In My Cart : 11 12 items';
preg_match_all('!\d+!', $str, $matches);
print_r($matches);
Gaurav
  • 28,447
  • 8
  • 50
  • 80
  • 2
    How can I get my number in a simple variable and not in Array ? – Bizboss Jun 08 '11 at 12:15
  • 38
    $var = implode(' ', $matches[0]); – Gaurav Jun 08 '11 at 12:16
  • 3
    @Bizboss In a similar vein, try `$newstr = preg_replace('!\d+!', '', $str);`. It will strip out all the digits from your string. Example: `$str = 'In My Cart : 11 12 items';` will output `In My Cart : items`. – Aether Jun 08 '11 at 13:02
  • `$str = intval(preg_replace('@[^0-9]@', "", "In My Cart : 11 12 items"));` – SpYk3HH Apr 29 '13 at 12:27
  • 87
    thi is not a resource friendly way. use `preg_replace("/[^0-9]/","",$string);` or `filter_var($str, FILTER_SANITIZE_NUMBER_INT);` – eapo Jul 21 '13 at 00:08
  • 8
    @eapo `filter_var($str, FILTER_SANITIZE_NUMBER_INT);` extracted digits, **plus** and **minus** sign. The regex extracted only digits! – PATROMO Nov 09 '16 at 09:36
  • @Akash Deep answer below is better than this one because it matches & fills in the array which is a bit of long process. `preg_replace` is the best solution for this one. – Ashiqur Rahman Oct 18 '18 at 07:53
  • The simple fact about this answer (despite being the accepted answer) is that `preg_match_all()` is an inappropriate tool when trying to isolate a single match. There is only one integer in the OP's sample string, so there is no point looking for more. – mickmackusa Nov 21 '20 at 13:25
  • This answer does not explain why this is the answer. – KIKO Software Jul 04 '21 at 11:38
  • @eapo Please do not use comments to express solutions -- this is what "answers" are for on Stack Overflow. – mickmackusa Jul 23 '21 at 07:26
376
preg_replace('/[^0-9]/', '', $string);

This should do better job!...

simhumileco
  • 31,877
  • 16
  • 137
  • 115
Mahipalsinh Ravalji
  • 3,889
  • 1
  • 12
  • 4
103

Using preg_replace:

$str = '(111) 111-1111';
$str = preg_replace('/\D/', '', $str);
echo $str;

Output: 1111111111

bob jomes
  • 271
  • 1
  • 4
  • 13
Akash Deep
  • 1,073
  • 1
  • 8
  • 10
  • 4
    It's working great. It converts `+387 (61) 634-783` string to `38761634783` directly. You don't have to take care of arrays like Gaurav's answer. – kuzey beytar Jul 02 '16 at 13:13
  • 1
    Definitly the best answer. http://sandbox.onlinephpfunctions.com/code/9d00d3e3e3c818267577fa9ae4531cc0ee38bb1a – Steffan Sep 29 '18 at 11:07
  • I recommend the `+` quantifier to match longer matches / fewer replacements. – mickmackusa Feb 19 '20 at 04:07
  • This answer appears to be answering a different question. The OP is only isolating one integer value from the string -- a number of items in a shopping cart. The understood scope of this page seems to have blown far out from what the OP has actually asked. This is the correct answer to a different question. – mickmackusa Nov 21 '20 at 13:05
24

For floating numbers,

preg_match_all('!\d+\.?\d+!', $string ,$match);

Thanks for pointing out the mistake. @mickmackusa

Yash
  • 929
  • 9
  • 25
  • It is actually wrong :) It should be `'!\d*.?\d+!'` – Yash Aug 15 '18 at 13:28
  • I would prefer to use `?` as the quantifier of the literal dot. I wouldn't expect a float value to contain multiple decimal point symbols. Yash's commented pattern is _wrong_ ironically. The dot needs a slash in front of it to make it literal. – mickmackusa Feb 19 '20 at 04:40
  • 1
    The OP's sample text indicates that there is no potential for a float value -- it makes no sense to have partial items in a shopping cart. There is also only one integer value in the sample text, so employing `preg_match_all()` is overkill. This is, at best, the correct answer to a different question. – mickmackusa Nov 21 '20 at 13:03
  • @mickmackusa You are absolutely right! I ended up on this question for a different use case and got an idea about how can I achieve it. The submitted answer was probably the solution I used at that time. – Yash Nov 22 '20 at 10:30
12

I do not own the credit for this, but I just have to share it. This regex will get numbers from a string, including decimal points/places, as well as commas:

/((?:[0-9]+,)*[0-9]+(?:\.[0-9]+)?)/

Cited from here:
php - regex - how to extract a number with decimal (dot and comma) from a string (e.g. 1,120.01)?

Community
  • 1
  • 1
mroncetwice
  • 420
  • 6
  • 16
  • This isn't validating the string for a comma between sets of three whole numbers. ...the problem with copy-pasting someone else's pattern and not understanding/testing it. – mickmackusa Feb 19 '20 at 04:44
  • Stack Overflow does not benefit when users copy-paste other Stack Overflow answers onto pages. If another Stack Overflow page contains the resolving advice for this page, then the correct behavior would be to use the hyperlink as a reason to close this page as a duplicate. Ultimately, this answer is simply not well suited to the OP's question. The OP will not possibly be isolating float values and we don't know if the there will be thousands separators. – mickmackusa Nov 21 '20 at 13:00
11

You can use preg_match:

$s = "In My Cart : 11 items";
preg_match("|\d+|", $s, $m);
var_dump($m);
Dmitri Gudkov
  • 2,093
  • 16
  • 15
10

Using preg_replace

$str = 'In My Cart : 11 12 items';
$str = preg_replace('/\D/', '', $str);
echo $str;
Hariadi
  • 606
  • 10
  • 17
10

The top resource-friendly solutions

<?php
    var $string = "In My Cart : 11 items";
?>

1. Fastest: filter_varFilters a variable with a specified filter

<?php
    filter_var($string, FILTER_SANITIZE_NUMBER_INT); // string(2) "11"
?>

2. Almost the fastest: str_replace — Replace all occurrences of the search string with the replacement string

<?php
    str_replace(array('In My Cart : ',' item', 's'),"", $string); // string(2) "11"
?>

3. Fast enough: preg_replacePerform a regular expression search and replace

<?php
    preg_replace("/[^0-9]/","",$string); // string(2) "11"
?>

However

  • the simplicity of str_replace cause speed, but even limited use cases
  • preg_replace is much more versatile than str_replace or filter_var
  • instead is possible to use a function to specify what to replace using preg_replace_callback
  • with preg_replace_callback can do multiple replacements in one call
  • filter_var limited in sanitation options
eapo
  • 1,053
  • 1
  • 19
  • 40
7
$value = '25%';

Or

$value = '25.025$';

Or

$value = 'I am numeric 25';
$onlyNumeric = filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);

This will return only the numeric value

Rakesh
  • 756
  • 8
  • 10
  • Why would the OP possibly want to accommodate float values? How might the OP's users have a fraction of an item in their shopping cart? This appears to be the correct answer to a different question. – mickmackusa Nov 21 '20 at 12:55
6

You can use following function:

function extract_numbers($string)
{
   preg_match_all('/([\d]+)/', $string, $match);

   return $match[0];
}
Ross Allen
  • 43,772
  • 14
  • 97
  • 95
Jasmeen
  • 876
  • 9
  • 16
  • There is no benefit to writing `\d` inside of a character class. Since you are accessing the fullstring match, there is no sense in writing a capture group into the pattern. – mickmackusa Feb 19 '20 at 04:30
  • The OP only has one integer to isolate -- `preg_match_all()` is an inappropriate tool for the question being asked. This is (at best) a working answer to a different question. – mickmackusa Nov 21 '20 at 12:57
6

Since there is only 1 numeric value to isolate in your string, I would endorse and personally use filter_var() with FILTER_SANITIZE_NUMBER_INT.

echo filter_var($string, FILTER_SANITIZE_NUMBER_INT);

A whackier technique which works because there is only 1 numeric value AND the only characters that come before the integer are letters, colons, or spaces is to use ltrim() with a character mask then cast the remaining string as an integer.

Demo

$string = "In My Cart : 11 items";
echo (int)ltrim($string, 'A..z: ');
// 11

If for some reason there was more than one integer value and you wanted to grab the first one, then regex would be a direct technique.

Demo

echo preg_match('/\d+/', $string, $m) ? $m[0] : '';

sscanf() is rather handy if you need to explicitly cast the numeric string as an integer (or float). If it is possible/unknown for the integer value to occur at the start of the string, then prepend a non-numeric character to the input string before scanning it. The following technique matches leading non-digits (and ignores them with * after the %), then matches the first occurring sequence of digits and casts the returned substring as an integer.

Demo

var_dump(sscanf(' ' . $string, '%*[^0-9]%d')[0]);

To adapt this technique to extract a float value, just change the d to f. For more information on the (currently undocumented) assignment suppression feature of sscanf(), see this post.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
5
preg_match_all('!\d+!', $some_string, $matches);
$string_of_numbers = implode(' ', $matches[0]);

The first argument in implode in this specific case says "separate each element in matches[0] with a single space." Implode will not put a space (or whatever your first argument is) before the first number or after the last number.

Something else to note is $matches[0] is where the array of matches (that match this regular expression) found are stored.

For further clarification on what the other indexes in the array are for see: http://php.net/manual/en/function.preg-match-all.php

Bradley Kovacs
  • 119
  • 1
  • 7
  • For the OP's sample input, `preg_match_all()` is needless extra work and it creates an `$matches` array with unnecessary depth. This looks like the kind of question that has completely forgotten what the OP has asked in the question. – mickmackusa Nov 21 '20 at 12:54
4

try this,use preg_replace

$string = "Hello! 123 test this? 456. done? 100%";
$int = intval(preg_replace('/[^0-9]+/', '', $string), 10);
echo $int;

DEMO

Dave
  • 3,073
  • 7
  • 20
  • 33
3

we can extract int from it like

$string = 'In My Car_Price : 50660.00';

echo intval(preg_replace('/[^0-9.]/','',$string));  # without number format   output: 50660
echo number_format(intval(preg_replace('/[^0-9.]/','',$string)));  # with number format  output :50,660

demo : http://sandbox.onlinephpfunctions.com/code/82d58b5983e85a0022a99882c7d0de90825aa398

user889030
  • 4,353
  • 3
  • 48
  • 51
  • Why are you accommodating decimal places? Did you read the OP's question? How might the OP's users have a fraction of an item in their shopping cart? – mickmackusa Nov 21 '20 at 12:49
3

Follow this step it will convert string to number

$value = '$0025.123';
$onlyNumeric = filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
settype($onlyNumeric,"float");

$result=($onlyNumeric+100);
echo $result;

Another way to do it :

$res = preg_replace("/[^0-9.]/", "", "$15645623.095605659");
jewelhuq
  • 1,210
  • 15
  • 19
  • Did you read the question? How might the OP's users have a fraction of an item in their cart? Or did you just read other answers and forget to see what the OP actually asked? – mickmackusa Nov 21 '20 at 12:48
2

other way(unicode string even):

$res = array();
$str = 'test 1234 555 2.7 string ..... 2.2 3.3';
$str = preg_replace("/[^0-9\.]/", " ", $str);
$str = trim(preg_replace('/\s+/u', ' ', $str));
$arr = explode(' ', $str);
for ($i = 0; $i < count($arr); $i++) {
    if (is_numeric($arr[$i])) {
        $res[] = $arr[$i];
    }
}
print_r($res); //Array ( [0] => 1234 [1] => 555 [2] => 2.7 [3] => 2.2 [4] => 3.3 ) 
2

An alternative solution with sscanf:

$str = "In My Cart : 11 items";
list($count) = sscanf($str, 'In My Cart : %s items');
Francesco Terenzani
  • 1,391
  • 7
  • 14
  • This is a very sensible technique for this specific case (where the non-numeric portion of the string is predictably static). It might be useful for researchers to understand that `%d` can also be used for casting the numeric substring as integer type data. https://3v4l.org/lLTXv @salathe mentioned [this technique back in 2011](https://stackoverflow.com/a/6278416/2943403), but was convinced by the OP to delete the answer on the grounds that the full string did not have a reliably static format. (The variability of the text should have been clarified by the OP.) – mickmackusa Jul 23 '21 at 07:21
-1

If you don't know which format the number is? int or floating, then use this :

$string = '$125.22';

$string2 = '$125';

preg_match_all('/(\d+.?\d+)/',$string,$matches); // $matches[1] = 125.22

preg_match_all('/(\d+.?\d+)/',$string2,$matches); // $matches[1] = 125
  • The capture groups are unnecessary because you are capturing the fullstring match -- effectively doubling the size of the matches array for no benefit. If the input strings are merely prepended with a `$`, then just use `ltrim($string, '$')`. – mickmackusa May 06 '22 at 01:26
-2

Depending on your use case, this might also be an option:

$str = 'In My Cart : 11 items';
$num = '';

for ($i = 0; $i < strlen($str); $i++) {

    if (is_numeric($str[$i])) {
        $num .= $str[$i];
    }
}

echo $num; // 11

Though I'd agree a regex or filter_var() would be more useful in the stated case.

kasimir
  • 1,506
  • 1
  • 20
  • 26
-2

for utf8 str:

function unicodeStrDigits($str) {
    $arr = array();
    $sub = '';
    for ($i = 0; $i < strlen($str); $i++) { 
        if (is_numeric($str[$i])) {
            $sub .= $str[$i];
            continue;
        } else {
            if ($sub) {
                array_push($arr, $sub);
                $sub = '';
            }
        }
    }

    if ($sub) {
        array_push($arr, $sub); 
    }

    return $arr;
}
  • This is definitely not `utf8` ready because you are not using `mb_` functions and you are using `[offset]` syntax to access each byte in the string. This unexplained answer is "no bueno". – mickmackusa May 06 '22 at 01:28
-2

This functions will also handle the floating numbers

$str = "Doughnuts, 4; doughnuts holes, 0.08; glue, 3.4";
$str = preg_replace('/[^0-9\.]/','-', $str);
$str = preg_replace('/(\-+)(\.\.+)/','-', $str);
$str = trim($str, '-');
$arr = explode('-', $str);
Khaldoon Masud
  • 300
  • 2
  • 4
  • Introducing hyphens to this process is entirely unnecessary. This answer also lacks an explanation of how it works and why you feel it is a good idea. – mickmackusa Feb 19 '20 at 04:33
-3

This script creates a file at first , write numbers to a line and changes to a next line if gets a character other than number. At last, again it sorts out the numbers to a list.

string1 = "hello my name 12 is after 198765436281094and14 and 124de"
f= open("created_file.txt","w+")
for a in string1:
    if a in ['1','2','3','4','5','6','7','8','9','0']:
        f.write(a)
    else:
        f.write("\n" +a+ "\n")
f.close()


#desired_numbers=[x for x in open("created_file.txt")]

#print(desired_numbers)

k=open("created_file.txt","r")
desired_numbers=[]
for x in k:
    l=x.rstrip()
    print(len(l))
    if len(l)==15:
        desired_numbers.append(l)


#desired_numbers=[x for x in k if len(x)==16]
print(desired_numbers)
ChrisF
  • 134,786
  • 31
  • 255
  • 325