Jak przetestować prawidłowy identyfikator UUID / GUID?

270

Jak sprawdzić, czy zmienna zawiera prawidłowy identyfikator UUID / GUID?

Obecnie jestem zainteresowany tylko sprawdzaniem poprawności typów 1 i 4, ale nie powinno to stanowić ograniczenia dla twoich odpowiedzi.

Marek Sebera
źródło
w formacie ciągu, nie szesnastkowy, nie bin, albo nie wiem o co prosisz
Marek Sebera
^ (\ {) {0,1} [0-9a-fA-F] {8} \ - [0-9a-fA-F] {4} \ - [0-9a-fA-F] {4} \ - [0-9a-fA-F] {4} \ - [0-9a-fA-F] {12} (\}) {0,1} $
Brandon Moretz
Jeśli nie możesz wykluczyć zmiennych zawierających łańcuch 32 kolejnych cyfr szesnastkowych (bez grupowania), spójrz na moją odpowiedź
Wolf

Odpowiedzi:

413

Obecnie identyfikatory UUID są określone w RFC4122. Często pomijanym przypadkiem na krawędzi jest NIL UUID, odnotowany tutaj . Poniższy wyrażenie regularne bierze to pod uwagę i zwróci dopasowanie dla UUID NIL. Zobacz poniżej UUID, który akceptuje tylko UUID inne niż NIL. Oba rozwiązania dotyczą wersji od 1 do 5 (patrz pierwszy znak trzeciego bloku).

Dlatego, aby sprawdzić poprawność UUID ...

/^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i

... zapewnia, że ​​masz kanonicznie sformatowany identyfikator UUID, który jest w wersji od 1 do 5 i jest odpowiednią wersją zgodnie z RFC4122.

UWAGA: Szelki {i }nie są kanoniczne. Są artefaktem niektórych systemów i zastosowań.

Łatwo zmodyfikować powyższe wyrażenie regularne, aby spełnić wymagania pierwotnego pytania.

WSKAZÓWKA: regex group / capture

Aby uniknąć dopasowania NIL UUID:

/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
Brykać
źródło
9
+1 Za wzmiankę o
Zespole
1
Myślę, że [1-5] [0-9a-f] {3} jest niepoprawny. Mam prawidłowy identyfikator UUID, który ma w tej części „b06a”, i to mi się nie udawało.
Felipe Brahm
1
@FelipeBrahm, [1-5] ma rację zgodnie z RFC, że 4 bity wskazują wersję, a jest tylko 5 wersji.
rvignacio
749d0000-0194-1005-2e05-08d61613bf2f zawodzi dla mnie w skrzypcach
rabuje
1
Z ciekawości (dlaczego) też nie byłyby poprawne: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
tjeerdnet
58

regex na ratunek

/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test('01234567-9ABC-DEF0-1234-56789ABCDEF0');

lub w nawiasach

/^\{?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}‌​\}?$/
ryanb
źródło
3
lub jeśli możesz mieć nawiasy kwadratowe: / ^ \ {? [0-9a-fA-F] {8} - [0-9a-fA-F] {4} - [0-9a-fA-F] {4} - [0-9a-fA-F] {4} - [0-9a-fA-F] {12} \}? $ /. Test („01234567-9ABC-DEF0-1234-56789ABCDEF0”);
ryanb
To nie jest całkiem poprawne. brakuje tego, że [1-5] (wersja) rozpoczyna trzeci blok, a [89AB] (wariant) rozpoczyna czwarty blok. Odpowiedź Gambola robi to dobrze.
Wolf
7
Bardziej zwięzła wersja (ignorowanie nawiasów):/^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/i
c24w 16.10.15
41

Jeśli chcesz sprawdzić lub sprawdzić konkretną wersję UUID, oto odpowiednie wyrażenia regularne.

Zauważ, że jedyną różnicą jest numer wersji , który wyjaśniono w 4.1.3. Versionrozdziale UUID 4122 RFC .

Numer wersji to pierwszy znak trzeciej grupy [VERSION_NUMBER][0-9A-F]{3}:

  • UUID v1:

    /^[0-9A-F]{8}-[0-9A-F]{4}-[1][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
  • UUID v2:

    /^[0-9A-F]{8}-[0-9A-F]{4}-[2][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
  • UUID v3:

    /^[0-9A-F]{8}-[0-9A-F]{4}-[3][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
  • UUID v4:

    /^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
  • UUID v5:

    /^[0-9A-F]{8}-[0-9A-F]{4}-[5][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
Ivan Gabriele
źródło
39

Jeśli używasz Node.js do programowania, zaleca się użycie pakietu o nazwie Validator. Zawiera wszystkie wyrażenia regularne wymagane do sprawdzania poprawności różnych wersji UUID oraz różne inne funkcje do sprawdzania poprawności.

Oto link npm: Validator

var a = 'd3aa88e2-c754-41e0-8ba6-4198a34aa0a2'
v.isUUID(a)
true
v.isUUID('abc')
false
v.isNull(a)
false
Neeraj Sharma
źródło
Ciekawe, ale wygląda na to, że oczekuje łączników? Oto cztery wyrażenia regularne, których obecnie używa - /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i i / lub /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i i / lub /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i i / lub /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i
ruffin
1
Walidator obsługuje tylko UUID v3-5, a nie v1
piątek,
13

Oprócz odpowiedzi Gambol, która wykona zadanie w prawie wszystkich przypadkach , wszystkie dotychczas udzielone odpowiedzi pominęły, że zgrupowane formatowanie (8-4-4-4-12) nie jest obowiązkowe do kodowania GUID w tekście . Jest używany bardzo często, ale oczywiście poprawny może być również zwykły łańcuch 32 cyfr szesnastkowych. [1] regex enh :

/^[0-9a-f]{8}-?[0-9a-f]{4}-?[1-5][0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}$/i

[1] Chodzi o to o sprawdzenie ing zmienna s, więc należy zaliczyć kształt nieprzyjazny dla użytkownika, jak również.

Wilk
źródło
To moja ulubiona. Jeszcze lepiej{?[0-9a-f]{8}-?[0-9a-f]{4}-?[1-5][0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}}?
Mike Nelson
10

Wszystkie opublikowane wcześniej wyrażenia specyficzne dla typu kończą się niepowodzeniem na UUID „zero 0”, zdefiniowanym w 4.1.7 RFC, jako:

Zero UUID jest specjalną formą UUID, która została określona tak, aby wszystkie 128 bitów było ustawione na zero: 00000000-0000-0000-0000-000000000000

Aby zmodyfikować odpowiedź Wolfa:

/^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-5][0-9a-f]{3}-?[089ab][0-9a-f]{3}-?[0-9a-f]{12}$/i

Lub, aby poprawnie wykluczyć „typ 0” bez wszystkich zer, mamy następujące (dzięki Łukaszowi):

/^(?:[0-9a-f]{8}-?[0-9a-f]{4}-?[1-5][0-9a-f]{3}-?[89ab][0-9a‌​-f]{3}-?[0-9a-f]{12}‌​|00000000-0000-0000-‌​0000-000000000000)$/‌​i
Evan Edwards
źródło
Pierwszy segment UUID zerowego UUID powinien mieć 8 zer, a nie 7. Podany regex nie zweryfikował go z 7.
Rich Seviora
2
Twój wygląda ładniej, ale dopuszcza niektóre nieprawidłowe UUID, np .: abcdef00-0000-0000-0000-000000000000 pasuje do wyrażenia regularnego. Ta regex będzie pasować do prawidłowych UUID, w tym zero:/^(?:[0-9a-f]{8}-?[0-9a-f]{4}-?[1-5][0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i
Łukasz
10

dzięki @usertatha z pewnymi modyfikacjami

function isUUID ( uuid ) {
    let s = "" + uuid;

    s = s.match('^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$');
    if (s === null) {
      return false;
    }
    return true;
}
Souhaieb
źródło
2

Myślę, że odpowiedź Gambola jest prawie idealna, ale źle interpretuje RFC 4122 § 4.1.1. Część wariantu trochę.

Obejmuje UUID wariantu 1 (10xx = 8..b), ale nie obejmuje wariantów wariantu 0 (0xxx = 0..7) i wariantu 2 (110x = c..d), które są zarezerwowane dla kompatybilności wstecznej, więc są technicznie poprawnymi identyfikatorami UUID. Wariant 4 (111x = e..f) jest rzeczywiście zarezerwowany do wykorzystania w przyszłości, więc obecnie nie są one ważne.

Ponadto typ 0 jest niepoprawny, ta „cyfra” może być równa 0, jeśli jest to NU UUID (jak wspomniano w odpowiedzi Evana ).

Myślę więc, że najdokładniejszym wyrażeniem regularnym zgodnym z aktualną specyfikacją RFC 4122 jest (w tym łączniki):

/^([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[0-9a-d][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i
                            ^                ^^^^^^
                    (0 type is not valid)  (only e..f variant digit is invalid currently)
B. Zoli
źródło
1

Użyj metody .match (), aby sprawdzić, czy String jest UUID.

public boolean isUUID(String s){
    return s.match("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
}
userTatha
źródło
Uncaught TypeError: s.matches nie jest funkcją
Deep Kakkar
1
Podany skrypt nie jest Javascriptem, o co poprosił OP.
StefanJanssen
Poprawiona odpowiedź na powyższe komentarze. Rozwiązanie działa teraz zgodnie z oczekiwaniami.
DeeZone
To wciąż nie jest js.
ktilcu
1

Nieco zmodyfikowana wersja powyższych odpowiedzi napisana w bardziej zwięzły sposób. Spowoduje to sprawdzenie poprawności dowolnego identyfikatora GUID z łącznikami (bez względu na łatwość modyfikacji, tak aby łączniki były opcjonalne). Będzie to również obsługiwać wielkie i małe litery, które stały się konwencją niezależnie od specyfikacji:

/^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}\-){3})([0-9a-fA-F]{12})$/i

Kluczem tutaj jest powtarzająca się część poniżej

(([0-9a-fA-F]{4}\-){3})

Który po prostu powtarza 4 wzorce znaków 3 razy

James Morrison
źródło
1
A-fpowinno być A-Ftak:/^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}\-){3})([0-9a-fA-F]{12})$/i
DeeZone
jeśli użyjesz case (/ i), po co powtarzać af, a następnie AF?
Nimrod
0

Dobrym sposobem na zrobienie tego w węźle jest użycie ajvpakietu ( https://github.com/epoberezkin/ajv ).

const Ajv = require('ajv');
const ajv = new Ajv({ allErrors: true, useDefault: true, verbose: true });
const uuidSchema = { type: 'string', format: 'uuid' };
ajv.validate(uuidSchema, 'bogus'); // returns false
ajv.validate(uuidSchema, 'd42a8273-a4fe-4eb2-b4ee-c1fc57eb9865'); // returns true with v4 GUID
ajv.validate(uuidSchema, '892717ce-3bd8-11ea-b77f-2e728ce88125'); // returns true with a v1 GUID
blackcatweb
źródło
-1

Myślę, że lepszym sposobem jest użycie metody statycznej fromString, aby uniknąć tych wyrażeń regularnych.

    id = UUID.randomUUID();
    UUID uuid = UUID.fromString(id.toString());
    Assert.assertEquals(id.toString(), uuid.toString());

Z drugiej strony

   UUID uuidFalse = UUID.fromString("x");

wyrzuca java.lang.IllegalArgumentException: Niepoprawny ciąg UUID: x

Werner Diwischek
źródło