5

Consider the following strings:

$strings = array(
    "8.-10. stage",
    "8. stage"
);

I would like to extract the first integer of each string, so it would return

8
8

I tried to filter out numbers with preg_replace but it returns all integers and I only want the first.

foreach($strings as $string)
{
    echo preg_replace("/[^0-9]/", '',$string);
}

Any suggestions?

Fredrik
  • 1,559
  • 4
  • 20
  • 39

8 Answers8

22

A convenient (although not record-breaking in performance) solution using regular expressions would be:

$string = "3rd time's a charm";

$filteredNumbers = array_filter(preg_split("/\D+/", $string));
$firstOccurence = reset($filteredNumbers);
echo $firstOccurence; // 3

Assuming that there is at least one number in the input, this is going to print the first one.

Non-digit characters will be completely ignored apart from the fact that they are considered to delimit numbers, which means that the first number can occur at any place inside the input (not necessarily at the beginning).

If you want to only consider a number that occurs at the beginning of the string, regex is not necessary:

echo substr($string, 0, strspn($string, "0123456789"));
Pepijn Olivier
  • 848
  • 1
  • 17
  • 29
Jon
  • 413,451
  • 75
  • 717
  • 787
  • 1
    the "reset" example results in PHP Strict Notices... "Strict Standards: Only variables should be passed by reference" – Kyle Anderson Aug 18 '15 at 06:11
  • How can I do this if I only want to return the alphabet? – xjshiya Mar 06 '19 at 08:10
  • @xjshiya check out this answer here https://stackoverflow.com/questions/6067592/regular-expression-to-match-only-alphabetic-characters/6067604 – Tami Oct 08 '21 at 14:20
9
preg_match('/\d+/',$id,$matches);
$id=$matches[0];
MERT DOĞAN
  • 2,470
  • 23
  • 25
8

If the integer is always at the start of the string:

(int) $string;

If not, then strpbrk is useful for extracting the first non-negative number:

(int) strpbrk($string, "0123456789");

Alternatives

These one-liners are based on preg_split, preg_replace and preg_match:

preg_split("/\D+/", "$string ")[1];
(int) preg_replace("/^\D+/", "", $string);
preg_match('/\d+/', "$string 0", $m)[0];

Two of these append extra character(s) to the string so empty strings or strings without numbers do not cause problems.

Note that these alternative solutions are for extracting non-negative integers only.

trincot
  • 263,463
  • 30
  • 215
  • 251
2

Try this:

$strings = array(
    "8.-10. stage",
    "8. stage"
);

$res   = array();
foreach($strings as $key=>$string){
  preg_match('/^(?P<number>\d)/',$string,$match);
  $res[$key] = $match['number'];
}

echo "<pre>";
print_r($res);
Prasanth Bendra
  • 29,105
  • 8
  • 50
  • 70
  • But only works for numbers with one digit at the start of the string, and if there is none, the line after causes an error. – trincot Feb 08 '16 at 22:30
1
foreach($strings as $string){
    echo preg_replace("/([0-9]+)\./", "\\1",$string);
}
Popnoodles
  • 28,388
  • 2
  • 42
  • 53
1
foreach($strings as $string){
 if(preg_match("/^(\d+?)/",$string,$res)) {
   echo $res[1].PHP_EOL;
 }
}
realization
  • 588
  • 1
  • 4
  • 5
1

if you have Notice in PHP 7 +

Notice: Only variables should be passed by reference in YOUR_DIRECTORY_FILE.php on line LINE_NUMBER

By using this code

echo reset(array_filter(preg_split("/\D+/", $string)));

Change code to

$var = array_filter(preg_split("/\D+/", $string));
return reset($var);

And enjoy! Best Regards Ovasapov

Arthur Hovasap
  • 225
  • 1
  • 2
  • 7
1

How to filter out all characters except for the first occurring whole integer:

It is possible that the target integer is not at the start of the string (even if the OP's question only provides samples that start with an integer -- other researchers are likely to require more utility ...like the pages that I closed today using this page). It is also possible that the input contains no integers, or no leading / no trailing non-numeric characters.

The following is a regex expression has two checks:

  1. It targets all non-numeric characters from the start of the string -- it stops immediately before the first encountered digit, if there is one at all.
  2. It matches/consumes the first encountered whole integer, then immediatelly forgets/releases it (using \K) before matching/consuming ANY encountered characters in the remainder of the string.

My snippet will make 0, 1, or 2 replacements depending on the quality of the string.

Code: (Demo)

$strings = [
    'stage', // expect empty string
    '8.-10. stage', // expect 8
    '8. stage', // expect 8
    '8.-10. stage 1st', // expect 8
    'Test 8. stage 2020', // expect 8
    'Test 8.-10. stage - 2020 test', // expect 8
    'A1B2C3D4D5E6F7G8', // expect 1
    '1000', // expect 1000
    'Test 2020', // expect 2020
];

var_export(
    preg_replace('/^\D+|\d+\K.*/', '', $strings)
);

Output:

array (
  0 => '',
  1 => '8',
  2 => '8',
  3 => '8',
  4 => '8',
  5 => '8',
  6 => '1',
  7 => '1000',
  8 => '2020',
)
mickmackusa
  • 37,596
  • 11
  • 75
  • 105