Reputation: 1821
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
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");
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
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:
\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
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
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
Reputation: 597
foreach($strings as $string){
if(preg_match("/^(\d+?)/",$string,$res)) {
echo $res[1].PHP_EOL;
}
}
Upvotes: 1
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