Fredrik
Fredrik

Reputation: 1821

Extract first integer in a string with PHP

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?

Upvotes: 7

Views: 26280

Answers (7)

trincot
trincot

Reputation: 350760

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.

Upvotes: 8

mickmackusa
mickmackusa

Reputation: 47992

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)
);

Or: (Demo)

preg_replace('/^\D*(\d+).*/', '$1', $strings)

Output:

array (
  0 => '',
  1 => '8',
  2 => '8',
  3 => '8',
  4 => '8',
  5 => '8',
  6 => '1',
  7 => '1000',
  8 => '2020',
)

Upvotes: 1

Jon
Jon

Reputation: 437554

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"));

Upvotes: 26

Arthur Hovasap
Arthur Hovasap

Reputation: 225

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

Upvotes: 1

MERT DOĞAN
MERT DOĞAN

Reputation: 3116

preg_match('/\d+/',$id,$matches);
$id=$matches[0];

Upvotes: 9

realization
realization

Reputation: 597

foreach($strings as $string){
 if(preg_match("/^(\d+?)/",$string,$res)) {
   echo $res[1].PHP_EOL;
 }
}

Upvotes: 1

Prasanth Bendra
Prasanth Bendra

Reputation: 32790

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);

Upvotes: 2

Related Questions