Pav
Pav

Reputation: 2328

PHP preg_match UUID v4

I've got a string that contains UUID v4

$uuid = 'http://domain.com/images/123/b85066fc-248f-4ea9-b13d-0858dbf4efc1_small.jpg';

How would i get the b85066fc-248f-4ea9-b13d-0858dbf4efc1 value from the above using preg_match()?
More info on UUID v4 can be be found here

Upvotes: 17

Views: 17094

Answers (4)

jetsetter
jetsetter

Reputation: 635

The accepted answer has several flaws:

  • It includes hidden characters that break the regex
  • It does not allow for uppercase letters (some or all)
  • It does not allow for optional dashes

See Wikipedia for details on allowed representations of a v4 UUID.

A regex check that meets the requirements above is:

preg_match(/(?i)[a-f0-9]{8}[\-]?[a-f0-9]{4}[\-]?4[a-f0-9]{3}[\-]?(8|9|a|b)[a-f0-9]{3}[\-]?[a-f0-9]{12}/, $uuid, $matches);

This option will meet most cases, however a more thorough version would address the following flaws:

  • It doesn't allow for the nil UUID (all 0) or the max UUID (all F)
  • It doesn't allow for the Windows-based format that includes leading and trailing braces ({...})

A regex check that meets these requirements as well is:

preg_match(/(?i){?[a-f0-9]{8}[\-]?[a-f0-9]{4}[\-]?(4[a-f0-9]{3}|[0]{4}|[F]{4})[\-]?((8|9|a|b)[a-f0-9]{3}|[0]{4}|[F]{4})[\-]?[a-f0-9]{12}}?/, $uuid, $matches);

These pieces mean:

  • (?i): force case insensitivity
  • {?: 0 or 1 opening braces
  • [a-f0-9]{8}: 8 allowed characters
  • [\-]?: 0 or 1 dashes
  • [a-f0-9]{4}: 4 allowed characters
  • [\-]?: 0 or 1 dashes
  • (4[a-f0-9]{3}|[0]{4}|[F]{4}): a 4 followed by 3 allowed characters, or 4 zeroes, or 4 Fs
  • [\-]?: 0 or 1 dashes
  • ((8|9|a|b)[a-f0-9]{3}|[0]{4}|[F]{4}): a 4 followed by 3 allowed characters, or 4 zeroes, or 4 Fs
  • [\-]?: 0 or 1 dashes
  • [a-f0-9]{12}: 12 allowed characters
  • }?: 0 or 1 closing braces

For any of you regex wizards out there, this could further be improved if it's possible to do the following:

  • Require that if one dash is present, all four dashes must be present
  • Only allow all zeroes or all Fs in some blocks if the entire UUID is all zeroes or Fs
  • Only allow an opening or closing brace if both are present

Upvotes: 0

user15059147
user15059147

Reputation: 1

When testing if string is matching, then don't forget ^ on beginning and $ on ending in pattern. Without them you can test, if string contains requested string, but not that it match requested string. '/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/'

Upvotes: -3

Shashank amin
Shashank amin

Reputation: 151

You can try this simple pattern for uuids

preg_match('/\w{8}-\w{4}-\w{4}-\w{4}-\w{12}/',$uuid,$matches);

Upvotes: 9

Nemoden
Nemoden

Reputation: 9056

$uuid = 'http://domain.com/images/123/b85066fc-248f-4ea9-b13d-0858dbf4efc1_small.jpg';
preg_match('!/images/\d+/([a-z0-9\-]*)_!i', $uuid, $m);

And

preg_match('/[a-f0-9]{8}\-[a-f0-9]{4}\-4[a-f0-9]{3}\-(8|9|a|b)[a-f0-9]{3‌​}\-[a-f0-9]{12}/', $uuid, $m);

works too. Taken from here, but I don't know if we can rely on that.

Upvotes: 23

Related Questions