1

I have a PHP app that get's a play store app data and I want to check if the data I am getting is the version number.

A version number can be 0.0.1 to 99.99.99 or I may be wrong with the version number limitations.

How can I properly use regular expressions to handle this job?

This is how I currently do it:

$list = ["hello", "0.23.2", "world"];

foreach($list as $l) {
    if (checkIfValidVersion($l)) {
       echo "valid version!";
    }
}

function checkIfValidVersion ($someString) {
    $split = explode(".", $someString);
    $isValid = false;

    foreach($split as $s) {
        $isValid = is_numeric($s) ? true : false;
    }

    return $isValid;
}
wobsoriano
  • 12,348
  • 24
  • 92
  • 162
  • 1
    Explode by `.` and compare every item. – u_mulder Mar 11 '19 at 13:12
  • Are you sure that `99.99.99` is the highest version number? That seems a little short-sighted considering that Chrome is up to `72.x.x` publically and `75.x` in Canary – MonkeyZeus Mar 11 '19 at 13:15
  • @MonkeyZeus I think I need to have more research regarding on that. Thanks! – wobsoriano Mar 11 '19 at 13:18
  • Definitely do more research because it looks like `1.1-demo` could be valid. https://developer.android.com/studio/publish/versioning – MonkeyZeus Mar 11 '19 at 13:55
  • Is there a reason for not knowing if you are dealing with a version number? If Google Play has an available API then I would imagine that the version is properly labeled within a JSON response. – MonkeyZeus Mar 11 '19 at 13:58
  • @MonkeyZeus currently there are no available API's online.. I mean free APIs – wobsoriano Mar 12 '19 at 00:44

6 Answers6

4

Simple regex would be \d+\.\d+\.\d+.

For php you can use preg_match. Check example on this link.

p.s. this is not strict check like version should be atleast 0.0.1 or max should be 99.99.99. It just checks for a pattern like below.

<number><dot><number><dot><number><dot>
shyammakwana.me
  • 5,562
  • 2
  • 29
  • 50
3

Assuming, as your examples in your question, you just want to match exactly 3 sets of numbers (assuming they can only be 2 digits containing only 0-9) check my solution here

[0-9]{1,2}\.[0-9]{1,2}\.?[0-9]{1,2}

This however has a few issues, as it won't work on less than 3 sets of digits, now if the play store doesn't allow that, great, but be aware that with the above regex version numbers like 1.0 and 1.1 will not match

Zachary Craig
  • 2,192
  • 4
  • 23
  • 34
3

Use:

^(\d?\d)\.(\d?\d)\.(\d?\d)$

That regex will match three groups of 1 or 2 digit numbers separated by dots. It is good to use ^ and $ with preg_match to make sure it will match the whole string and not a string containing the version part, e.g. something1.0.0something.

Examples:

preg_match("/^(\d?\d)\.(\d?\d)\.(\d?\d)$/", "1.0.0"); // Match
preg_match("/^(\d?\d)\.(\d?\d)\.(\d?\d)$/", "99.99.99"); // Match
preg_match("/^(\d?\d)\.(\d?\d)\.(\d?\d)$/", "99.699.99"); // Not match
DontVoteMeDown
  • 21,122
  • 10
  • 69
  • 105
2

If you want to enforce the lower limit of 0.0.1 then this will work:

<?php
function is_valid_version( $version )
{
    // Assume the input is invalid
    $return = false;

    // Make sure we can explode() the input
    if( is_scalar( $version ) )
    {
        // Explode on periods
        $version = explode( '.', (string)$version );

        // We should have exactly items
        if( count( $version ) === 3 )
        {
            // All three items should be digits
            if(
                ctype_digit( $version[ 0 ] ) &&
                ctype_digit( $version[ 1 ] ) &&
                ctype_digit( $version[ 2 ] )
            )
            {
                // At least one digit needs to not be zero
                // 0.0.0 should be invalid
                // If you want the upper limit to be 99.99.99 then this is where you should do it
                if(
                    (int)$version[ 0 ] !== 0 ||
                    (int)$version[ 1 ] !== 0 ||
                    (int)$version[ 2 ] !== 0
                )
                {
                    $return = true;
                }
            }
        }
    }

    return $return;
}

var_dump( is_valid_version( '1.2.3' ) ); // true
var_dump( is_valid_version( '0.0.0' ) ); // false
var_dump( is_valid_version( '0.0.1' ) ); // true
var_dump( is_valid_version( '0.1.0' ) ); // true
var_dump( is_valid_version( '100.53456.fgdf' ) ); //false
var_dump( is_valid_version( array() ) ); //false
MonkeyZeus
  • 20,375
  • 4
  • 36
  • 77
1

If you just explode the dot (.) then each item is limited to a maximum length of 2.

$version = "25.22.01";
$bool = true;
foreach(explode(".", $version) as $part) {
  if(strlen($part) > 2) {
    $bool = false;
  }
}

// Expected result: "true"
var_dump($bool);

Here is a working example at 3v4l.org.

Malekai
  • 4,765
  • 5
  • 25
  • 60
Andreas
  • 23,610
  • 6
  • 30
  • 62
1

Improving on shyammakwana.me's answer, I'd suggest using:

\d{1,2}\.\d{1,2}\.\d{1,2}

Because the + plus quantifier is greedy by default and would match:

9999323.32532553.893588972350897327

As well as:

1.1.1

Using curly braces gives allows you to be more specific and determine if the specified version isn't formatted properly.

If you wanted to, you could get rid of the second number and just use {1,} to match one or more numbers.

Malekai
  • 4,765
  • 5
  • 25
  • 60