Check if a UUID is valid without using regexes

JavaScript ES6, 73 55 56 chars

s=>s.split`-`.map(x=>x.length+`0x${x}0`*0)=="8,4,4,4,12"

The previous 55 chars version has a problem with trailing spaces in group:

s=>s.split`-`.map(x=>x.length+("0x"+x)*0)=="8,4,4,4,12"
// "00000000-0000-0000-000 -000000000000" true

Test:

f=s=>s.split`-`.map(x=>x.length+`0x${x}0`*0)=="8,4,4,4,12"
;`0FCE98AC-1326-4C79-8EBC-94908DA8B034
0fce98ac-1326-4c79-8ebc-94908da8b034
0FCE98ac-1326-4c79-8EBC-94908da8B034
0GCE98AC-1326-4C79-8EBC-94908DA8B034
0FCE98AC-13264C79-8EBC-94908DA8B034
0FCE98AC-13264-C79-8EBC-94908DA8B034
0FCE98ACD-1326-4C79-8EBC-94908DA8B034
0FCE98AC-1326-4C79-8EBC-94908DA8B034-123
00000000-0000-0000-0000-000000000000
D293DBB2-0801-4E60-9141-78EAB0E298FF
0FCE98AC-1326-4C79-8EBC-94908DA8B034-
00000000-0000-0000-000 -000000000000`.split(/\n/g).every(s=>f(s)==/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i.test(s))

CJam, 31 30 29 bytes

8 4__C]Nf*'-*qA,s'G,_el^+Ner=

Run all test cases here.

Explanation

Instead of pattern matching the input directly, we're first transforming it to a simpler form which can be easily compared against a single pattern string.

8 4__C] e# Push the array of segment lengths, [8 4 4 4 12].
Nf*     e# Turn that into strings of linefeeds of the given length.
'-*     e# Join them by hyphens, giving "NNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN".
q       e# Read the input.
A,s     e# Push the string "0123456789".
'G,_el^ e# Push the string "ABCDEFabcdef".
+       e# Concatenate the two strings.
N       e# Push a linefeed.
er      e# Replace all hexadecimal digits with linefeeds.
=       e# Check for equality with the pattern string.

PowerShell, 29 21 84 49 37 Bytes

param($g)@{36=$g-as[guid]}[$g.length]

Many thanks to the folks in the comments assisting with this golfing to keep up with the changing rules -- TessellatingHeckler, iFreilicht, Jacob Krall, and Joey. Please see the edit history for revisions and older versions.

This revision takes input as $g, then creates a new hash table @{} with one element, index 36 is set equal to $g-as[guid]. This uses the built-in -as operator to attempt conversion between two .NET data types -- from [string] to [guid]. If the conversion is successful, a [guid] object is returned, else $null is returned. This portion ensures that the input string is a valid .NET GUID.

The next step is to index into the hash table with [$g.length]. If $g is not exactly 36 characters in length, the hash table will return $null, which will be output as a falsey value. If $g is 36 characters in length, then the result of the .NET call will be output. If $g is not a valid .NET GUID (in any form), then it will output $null as a falsey value. Otherwise it will output a .NET GUID object as a truthy value - the only way that can be output is if it matches the requested format of the challenge.

Examples

Here I am encapsulating the script call in parens and explicitly casting as a Boolean for clarity.

PS C:\Tools\Scripts\golfing> [bool](.\check-if-a-uuid-is-valid.ps1 '0FCE98AC-1326-4C79-8EBC-94908DA8B034')
True

PS C:\Tools\Scripts\golfing> [bool](.\check-if-a-uuid-is-valid.ps1 '0FCE98AC-1326-4C79-8EBC-94908DA8B034D')
False

PS C:\Tools\Scripts\golfing> [bool](.\check-if-a-uuid-is-valid.ps1 '0FCE98AC13264C798EBC94908DA8B034')
False