Check for number in a string

Asked

Viewed 7,723 times

4

I need to do several validations in my form, and one of them is to check if the name entered contains number somewhere in the string whether at the beginning middle or end, I already tried to use is_numeric but it only worked if it were numbers, not a mixture of numbers with letters.

What I could do?

  • Serves to use regex?

  • http://php.net/manual/en/function.preg-match.php

  • http://stackoverflow.com/a/901738/1244639, other option

4 answers

8

Studies on regular expressions and take a look at preg_match()

if( preg_match('/\d+/', $nome)>0 ){
   echo 'Seu nome tem algum numero';
}

This regex will detect if you have one or more numbers anywhere in the string.

7


Filter_var with FILTER_SANITIZE_NUMBER_INT

A way to check whether the string contains at least one number, without using regular expression (which is usually slower), is using the function filter_var.

Behold:

var_dump(filter_var('teste', FILTER_SANITIZE_NUMBER_INT)); // ''

var_dump(filter_var('teste1', FILTER_SANITIZE_NUMBER_INT)); // '1'

The flag FILTER_SANITIZE_NUMBER_INT is responsible for removing all non-numeric characters from the expression and returning only numbers. So we can know if there are numbers in the string checking whether she has not returned a string empty.

Example:

filter_var($valor, FILTER_SANITIZE_NUMBER_INT)) !== ''

We have to beware, for the blessed of PHP compares '0' == false as an expression true. So that’s why I used the comparison ! == ''. Another important detail is that if you pass one array in the first parameter of filter_var (with FILTER_SANITIZE_NUMBER_INT) he will return false instead of ''.

This could cause a "boolean mess".

So thinking of the point of view I passed above, the smartest thing to do is :

Matching FILTER_SANTIZE_NUMBER_INT with is_numeric

Since what returns from FILTER_SANTIZE_NUMBER_INT will only return numbers, so we can use the function is_numeric whether the result of filter_var is a number or not, which is present in the string.

function contains_number($string) {
   return is_numeric(filter_var($string, FILTER_SANITIZE_NUMBER_INT));
}
  • 2

    ctype_alnum('a'); returns true?

  • Yes @jbueno. That’s why I’m improving the details.

  • I was just going to say that your answer is wrong :p

  • But the other answer also does not speak of alphanumeric. It speaks only of numbers.

  • How not? It does not check if it has a number in the middle of the string?

  • @jbueno but the other answer speaks only of numbers. If I pass only numbers, and not letters, it will be accepted. But this was also not what the AP asked, he asked just to know if there is number or not. The two answers now meet

  • Now @Wallacemaxters +1

  • In my opinion I should remove the first part of the answer with ctype_alnum(), as it does not solve the problem. The use of filter_var() resolves - although it was not created for this as regular expressions.

  • @Newtonwagner removed. I also agree with you

Show 4 more comments

4

Below are some other alternatives.

filter_var

You can use the function filter_var to filter only numbers (and + and -) using the filter FILTER_SANITIZE_NUMBER_INT, if filtering fails, the result is false:

function encontrouNumeros($string) {
    return (filter_var($string, FILTER_SANITIZE_NUMBER_INT) === '' ? false : true);
}

var_dump(encontrouNumeros("stack")); // bool(false)
var_dump(encontrouNumeros("st4ck")); // bool(true)

For floating point use FILTER_SANITIZE_NUMBER_FLOAT.

ctype_digit

Like suggested by Wallace Maxters, can also use the function ctype_digit, is returned true if all the characters in the string are numerical, false otherwise.

To check whether a string contains numbers, check character by character in a loop:

function encontrouNumeros2($string) {
    $indice = 0;
    while ($indice < strlen($string)) {
        if (ctype_digit($string[$indice]) === true) return true;
        $indice++;
    }
    return false;
}

var_dump(encontrouNumeros2("stack")); // bool(false)
var_dump(encontrouNumeros2("st4ck")); // bool(true)

strpbrk

The function strpbrk search in string by one of the characters in a set, returns a string starting from the found character, or false if none of the characters in the set are found:

function encontrouNumeros3($string) {
    return strpbrk($string, '0123456789') !== false;
}

var_dump(encontrouNumeros3("stack")); // bool(false)
var_dump(encontrouNumeros3("st4ck")); // bool(true)
  • I also put this in the answer, but I’m only afraid of one thing: In php '0' == false also returns false. And '0' is a number (I’m stunned, but I saw it here in the same tests). If you notice, I put !== '' not to give problem.

  • @Wallacemaxters You’re right, I’ll see that.

  • 1

    I thought it was smart to put the is_numeric as a result of filter_var. Maybe you want a suggestion for your answer: how about using ctype_digit as a result of their filter_var?

  • @Wallacemaxters I fixed the bug, now returns true if filter_var filter correctly and false if not. You mentioned the ctype_digit, that gave me the idea to use it on a loop, so I put another alternative. :)

  • 2

    ! in_array(false, array_map('ctype_digit', str_split($value)))

  • 1

    huehuehuehuehue

Show 1 more comment

1

The question does not specify whether you want to get the position of what you find as numeric, so by focusing on the section that says you only need to find if there are numeric characters, you would do something like this.

function NumbersOnly($str, $float = false)
{
    $r = '';
    if ($float) {
        $r = '.';
        $str = str_replace(',', $r, $str);
    }
    return preg_replace('#[^0-9'.$r.']#', '', mb_convert_kana($str, 'n'));
}

$str = 'foo2';

if (!empty(NumbersOnly($str))) {
    echo 'Encontrou números';
} else {
    echo 'NÃO encontrou números';
}

Caution with Zenkaku numeric characters

The function filter_var() does not consider Zenkaku characters 1234567890 which are different from ASCII characters 1234567890. Notice how visually the size is different.

If you want something more consistent that detects Zenkaku characters, the above example is safer.

A test with the 4 versions, including the ones posted in the other answers:

function phpfilter($str) {
    return filter_var($str, FILTER_SANITIZE_NUMBER_INT);
}
function encontrouNumeros($string) {
    return (filter_var($string, FILTER_SANITIZE_NUMBER_INT) === '' ? false : true);
}
function NumbersOnly($str, $float = false)
{
    $r = '';
    if ($float) {
        $r = '.';
        $str = str_replace(',', $r, $str);
    }
    return preg_replace('#[^0-9'.$r.']#', '', mb_convert_kana($str, 'n'));
}


$str = 'foo3'; // testando com zenkaku
//$str = 'foo'; // sem número
//$str = 'foo3'; // número ascii

if (!empty(phpfilter($str))) {
    echo 'Encontrou números';
} else {
    echo 'NÃO encontrou números';
}
echo '<br>';
if (encontrouNumeros($str)) {
    echo 'Encontrou números';
} else {
    echo 'NÃO encontrou números';
}
echo '<br>';
if (!empty(NumbersOnly($str))) {
    echo 'Encontrou números';
} else {
    echo 'NÃO encontrou números';
}

echo '<br>';
if( preg_match('/\d+/', $str)>0 ){
    echo 'Encontrou números';
} else {
    echo 'NÃO encontrou números';
}

Alternative with strpbrk()

As posted in another reply, we have this function serves very well with a much cleaner code:

function encontrouNumeros3($string) {
    return strpbrk($string, '0123456789') !== false;
}

var_dump(encontrouNumeros3("st4ack"));

However, again one should be careful with the zenkaku characters. To do this, tap add them into the function.

function encontrouNumeros3($string) {
    return strpbrk($string, '01234567891234567890') !== false;
}

var_dump(encontrouNumeros3("st4ack")); // retorna true

The difference between the function of the first example NumbersOnly() and strpbrk() is that one sanitizes and another returns boolean if it finds any of the characters specified in the second parameter. Choose what is convenient for your case.

Finalizing

Something that may be the simplest to the focus of the question:

if (preg_match('/\d+/', mb_convert_kana($str, 'n')) > 0) {
    echo 'Encontrou números';
} else {
    echo 'NÃO encontrou números';
}

I didn’t do a performance test. But the idea is to sanitize with mb_convert_kana() and apply any other solution. Just see which one is faster.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.