Làm thế nào để kiểm tra UUID / GUID hợp lệ?


270

Làm cách nào để kiểm tra xem biến có chứa định danh UUID / GUID hợp lệ không?

Tôi hiện chỉ quan tâm đến việc xác thực loại 1 và 4, nhưng nó không phải là giới hạn cho câu trả lời của bạn.


ở định dạng chuỗi, không phải hex, không phải bin, hoặc tôi không biết bạn yêu cầu gì
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

Nếu bạn không thể loại trừ các biến có chứa một chuỗi gồm 32 chữ số hex liên tiếp (không nhóm), hãy xem câu trả lời của tôi
Wolf

Câu trả lời:


413

Hiện tại, UUID được quy định trong RFC4122. Một trường hợp cạnh thường bị bỏ qua là NIL UUID, được ghi chú ở đây . Regex sau đây tính đến điều này và sẽ trả về một trận đấu cho NIL UUID. Xem bên dưới để biết UUID chỉ chấp nhận UUID không NIL. Cả hai giải pháp này đều dành cho phiên bản 1 đến 5 (xem ký tự đầu tiên của khối thứ ba).

Do đó, để xác thực 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

... Đảm bảo bạn có UUID được định dạng chính tắc từ Phiên bản 1 đến 5 và là Biến thể phù hợp theo RFC4122.

LƯU Ý: Niềng răng {}không hợp quy. Chúng là một tạo tác của một số hệ thống và tập quán.

Dễ dàng sửa đổi regex trên để đáp ứng các yêu cầu của câu hỏi ban đầu.

GỢI Ý: nhóm regex / chụp

Để tránh kết hợp 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


1
Tôi nghĩ rằng [1-5] [0-9a-f] {3} là không chính xác. Tôi có một UUID hợp lệ có "b06a" trong phần đó và điều này đã thất bại đối với tôi.
Felipe Brahm

1
@FelipeBrahm, [1-5] đúng theo RFC, rằng 4 bit chỉ ra phiên bản và chỉ có 5 phiên bản.
rvignacio

749d0000-0194-1005-2e05-08d61613bf2f thất bại đối với tôi trong câu đố
cướp

1
Vì tò mò, (tại sao) những điều sau đây cũng không có giá trị: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
tjeerdnet

58

regex để giải cứu

/^[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');

hoặc có dấu ngoặc

/^\{?[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}‌​\}?$/

3
hoặc nếu bạn có thể có dấu ngoặc: / ^ \ {? [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} \}? $ /. Thử nghiệm ('01234567-9ABC-DEF0-1234-56789ABCDEF0');
ryanb

Điều này không hoàn toàn chính xác. nó nhớ rằng [1-5] (phiên bản) bắt đầu khối thứ 3 và [89AB] (biến thể) bắt đầu khối thứ 4. Câu trả lời của Gambol làm đúng.
Sói

7
Phiên bản ngắn gọn hơn (bỏ qua dấu ngoặc):/^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/i
c24w

41

Nếu bạn muốn kiểm tra hoặc xác nhận một phiên bản UUID cụ thể, đây là các biểu thức chính tương ứng.

Lưu ý rằng sự khác biệt duy nhất là số phiên bản , được giải thích trong 4.1.3. Versionchương của UUID 4122 RFC .

Số phiên bản là ký tự đầu tiên của nhóm thứ ba [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

39

Nếu bạn đang sử dụng Node.js để phát triển, bạn nên sử dụng gói có tên là Trình xác thực. Nó bao gồm tất cả các biểu thức cần thiết để xác thực các phiên bản khác nhau của UUID cộng với bạn có các chức năng khác để xác thực.

Đây là liên kết npm: Trình xác thực

var a = 'd3aa88e2-c754-41e0-8ba6-4198a34aa0a2'
v.isUUID(a)
true
v.isUUID('abc')
false
v.isNull(a)
false

Thú vị, nhưng có vẻ như nó mong đợi dấu gạch ngang? Dưới đây là bốn biểu thức hiện đang sử dụng - /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i và / hoặc /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i và / hoặc /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i / hoặc /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i
ruffin

1
Trình xác nhận chỉ hỗ trợ UUID v3-5 chứ không phải v1
peteb

13

Bên cạnh câu trả lời của Gambol sẽ thực hiện công việc trong gần như tất cả các trường hợp , tất cả các câu trả lời cho đến nay đã bỏ lỡ rằng định dạng được nhóm (8-4-4-4-12) không bắt buộc phải mã hóa GUID trong văn bản . Nó được sử dụng rất thường xuyên nhưng rõ ràng cũng có một chuỗi đơn giản gồm 32 chữ số thập lục phân có thể hợp lệ. [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] Câu hỏi đặt ra là về kiểm tra ing biến s, vì vậy chúng ta nên bao gồm các hình thức sử dụng không thân thiện là tốt.


Đây là fave của tôi. Thậm chí tốt hơn{?[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

Tất cả các biểu thức cụ thể theo loại được đăng cho đến nay đều không thành công trên "loại 0" Nil UUID, được định nghĩa trong 4.1.7 của RFC là:

UUID nil là dạng UUID đặc biệt được chỉ định để có tất cả 128 bit được đặt thành 0: 00000000-0000-0000-0000-000000000000

Để sửa đổi câu trả lời của Wolf:

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

Hoặc, để loại trừ đúng "loại 0" mà không có tất cả các số không, chúng tôi có các mục sau (nhờ Luke):

/^(?:[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

Phân đoạn UUID đầu tiên của UUID không có 8 số 0, không phải 7. Số regex được cung cấp không xác thực nó với 7.
Rich Seviora

2
Bạn trông đẹp hơn nhưng cho phép một số UUID không hợp lệ, ví dụ: abcdef00-0000-0000-0000-000000000000 sẽ khớp với biểu thức chính quy của bạn. Regex này sẽ khớp với các UUID hợp lệ, bao gồm cả số không:/^(?:[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
Luke

10

cảm ơn @usertatha với một số sửa đổi

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;
}

2

Tôi nghĩ rằng câu trả lời của Gambol gần như hoàn hảo, nhưng nó giải thích sai về RFC 4122 § 4.1.1. Phần biến thể một chút.

Nó bao gồm các biến thể Variant-1 UUID (10xx = 8..b), nhưng không bao gồm các biến thể Variant-0 (0xxx = 0..7) và Variant-2 (110x = c..d) được dành riêng cho khả năng tương thích ngược, vì vậy chúng là UUID hợp lệ về mặt kỹ thuật. Biến thể-4 (111x = e..f) thực sự được dành riêng cho sử dụng trong tương lai, vì vậy chúng hiện không hợp lệ.

Ngoài ra, loại 0 không hợp lệ, "chữ số" đó chỉ được phép là 0 nếu đó là NIL UUID (như được đề cập trong câu trả lời của Evan ).

Vì vậy, tôi nghĩ rằng regex chính xác nhất tuân thủ thông số RFC 4122 hiện tại là (bao gồm cả dấu gạch nối):

/^([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)

1

Sử dụng phương thức .match () để kiểm tra xem String có phải là UUID hay không.

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}$");
}

Uncaught TypeError: s.matches không phải là một chức năng
Deep Kakkar

1
Kịch bản đã cho không phải là Javascript, đó là những gì OP yêu cầu.
StefanJanssen

Điều chỉnh câu trả lời cho ý kiến ​​địa chỉ ở trên. Giải pháp bây giờ hoạt động như mong đợi.
DeeZone

Đó vẫn chưa phải là js.
ktilcu

1

Một phiên bản sửa đổi một chút của các câu trả lời ở trên được viết theo cách ngắn gọn hơn. Điều này sẽ xác nhận bất kỳ GUID nào bằng dấu gạch nối (tuy nhiên dễ dàng sửa đổi để tạo dấu gạch nối tùy chọn). Điều này cũng sẽ hỗ trợ các ký tự chữ hoa và chữ thường đã trở thành quy ước bất kể đặc điểm kỹ thuật:

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

Chìa khóa ở đây là phần lặp lại bên dưới

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

Mà chỉ đơn giản là lặp lại 4 mẫu char 3 lần


1
A-fnên A-Fnhư vậy:/^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}\-){3})([0-9a-fA-F]{12})$/i
DeeZone

nếu bạn nhập trường hợp (/ i), tại sao lặp lại af và sau đó AF?
Nimrod

0

Một cách tốt để làm điều đó trong Node là sử dụng ajvgói ( 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

-1

Tôi nghĩ rằng một cách tốt hơn là sử dụng phương thức tĩnh từString để tránh các biểu thức chính quy đó.

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

Mặt khác

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

ném java.lang.IllegalArgumentException: Chuỗi UUID không hợp lệ: x

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.