0

How can I find all the numbers that are contained in a string except the ones that have also a letter in them (like A1)? For example in a String "saddfs 2300 dfsfd 45 A3 A6" I only want to get 2300 and 45.

I know that

preg_match_all('!\d+!', $string, $nums);

can find all numbers, but I dont want to find the numbers from A3,A6 too.

Thanks!

2 Answers 2

2

Just use word boundary or string boundaries:

preg_match_all('!(^|\b)\d+(\b|$)!', $string, $nums);

Some tests:

php > preg_match_all('!(^|\b)\d+(\b|$)!', 'saddfs 2300 dfsfd 45 A3 A6', $nums);
php > print_r($nums[0]);
Array
(
    [0] => 2300
    [1] => 45
)
php > preg_match_all('!(^|\b)\d+(\b|$)!', 'saddfs 2300 dfsfd 45 A3 A6 123', $nums);
php > print_r($nums[0]);
Array
(
    [0] => 2300
    [1] => 45
    [2] => 123
)
php > preg_match_all('!(^|\b)[0-9]+(\b|$)!', '789 saddfs 2300 dfsfd 45 A3 A6 123', $nums);
php > print_r($nums[0]);
Array
(
    [0] => 789
    [1] => 2300
    [2] => 45
    [3] => 123
)

UPDATE: changed \d to [0-9] per Zsolt Szilagy's suggestion.

Sign up to request clarification or add additional context in comments.

1 Comment

By the way, you might want to replace \d with [0-9]. \d also finds chinese, thai and japanese digits (a total of over 1000 chars), and those could bypass security checks and blow the database when dealing with deffectivly encoded data.
2

Non-robust, quick-and-dirty -- and wrong -- solution:

$ php -a
Interactive shell

php > preg_match_all('/\W\d+\W/', 'saddfs 2300 dfsfd 45 A3 A6', $matches);
php > print_r($matches);
Array
(
    [0] => Array
        (
            [0] =>  2300
            [1] =>  45
        )

)

Update Per Aleks G suggestion, laying out the pitfalls to this solution:

First problem: this fails to match pure numbers at the strict beginning or ending of a string. To do that, follow Aleks G pattern, which puts anchor characters in capturing sub-patterns:

preg_match_all('/(^|\W)\d+(\W|$)/', '2300 df A6 242 sfd 45', $matches);

You could make the pattern non-capturing ('/(?:^|\W)\d+(?:\W|$)/') to signal your intent that the parentheses are for grouping, not for capturing -- but this is purely optional as the values you still want remain in $matches[0].

Second problem: \b and \W are not quite the same thing. \b is a "word boundary" while \W is "not a word character". Compare the result of Aleks G and my answer and you'll see that \b gives back pure numbers while \W gives back surrounding space.

Update Per Zsolt Szilagy comment, \d matches the digits in the current character set, so for languages with more digit characters (eg Chinese) you won't get the 0 through 9 expected. Use the character class [0-9] for that.

3 Comments

This will not work for numbers at the beginning or end of string. Test your code with string 'saddfs 2300 dfsfd 45 A3 A6 123' - the last 123 will not be matched.
@AleksG: I am aware of that. Something has to be left for the reader to determine.
If you are aware of it and purposefully leave it to the OP to determine, you should explicitly state so in your answer. Otherwise it comes across as either sloppiness or laziness.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.