จะทดสอบ UUID / GUID ที่ถูกต้องได้อย่างไร


270

จะตรวจสอบว่าตัวแปรมีตัวระบุ UUID / GUID ที่ถูกต้องได้อย่างไร

ขณะนี้ฉันสนใจเฉพาะการตรวจสอบประเภท 1 และ 4 แต่ไม่ควร จำกัด เฉพาะคำตอบของคุณ


ในรูปแบบของสตริงไม่ใช่ hex ไม่ใช่ bin หรือไม่รู้ว่าคุณถามอะไร
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} $
แบรนดอน Moretz

หากคุณไม่สามารถยกเว้นตัวแปรที่มีห่วงโซ่ของเลขฐานสิบหกที่ต่อเนื่องกัน 32 ตัว (โดยไม่รวมกลุ่ม) ให้ดูที่คำตอบของฉัน
Wolf

คำตอบ:


413

ขณะนี้ UUID มีการระบุไว้ใน RFC4122 กรณีที่ขอบมักจะถูกละเลยเป็น NIL UUID ตั้งข้อสังเกตที่นี่ regex ต่อไปนี้พิจารณาสิ่งนี้และจะส่งคืนการแข่งขันสำหรับ NIL UUID ดูด้านล่างสำหรับ UUID ซึ่งยอมรับเฉพาะ UIL ที่ไม่ใช่ NIL เท่านั้น โซลูชันทั้งสองนี้ใช้สำหรับเวอร์ชัน 1 ถึง 5 (ดูอักขระตัวแรกของบล็อกที่สาม)

ดังนั้นเพื่อตรวจสอบ 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

... ทำให้แน่ใจว่าคุณมีรูปแบบ UUID ที่เป็นรูปแบบมาตรฐานซึ่งเป็นรุ่นที่ 1 ถึง 5 และเป็นตัวแปรที่เหมาะสมตาม RFC4122

หมายเหตุ: การจัดฟัน{และ}ไม่ใช่แบบบัญญัติ มันเป็นสิ่งประดิษฐ์ของระบบและประเพณีบางอย่าง

ง่ายต่อการแก้ไข regex ข้างต้นเพื่อตอบสนองความต้องการของคำถามเดิม

คำแนะนำ: กลุ่ม / การบันทึก regex

วิธีหลีกเลี่ยงการจับคู่ 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

9
+1 สำหรับการกล่าวถึงInternet Engineering Task Force (IETF)
mate64

1
ฉันคิดว่า [1-5] [0-9a-f] {3} ไม่ถูกต้อง ฉันมี UUID ที่ถูกต้องซึ่งมี "b06a" ในส่วนนั้นและนี่ล้มเหลวสำหรับฉัน
Felipe Brahm

1
@FelipeBrahm [1-5] ถูกต้องตาม RFC นั้น 4 บิตระบุรุ่นและมีเพียง 5 รุ่นเท่านั้น
rvignacio

749d0000-0194-1005-2e05-08d61613bf2f ล้มเหลวสำหรับฉันในซอ
robs

1
จากความอยากรู้ (ทำไม) สิ่งต่อไปนี้จะไม่ถูกต้องเช่นกัน: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
tjeerdnet

58

regex เพื่อช่วยเหลือ

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

หรือด้วยวงเล็บ

/^\{?[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
หรือถ้าคุณอาจมีวงเล็บ: / ^ \ {? [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

มันไม่ถูกต้องนัก มันพลาดว่า [1-5] (เวอร์ชั่น) เริ่มบล็อกที่ 3 และ [89AB] (ตัวแปร) เริ่มบล็อกที่ 4 คำตอบของ Gambolมันถูกต้อง
Wolf

7
รุ่นที่กระชับมากขึ้น (ไม่สนใจวงเล็บ):/^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/i
c24w

41

หากคุณต้องการตรวจสอบหรือตรวจสอบความถูกต้องของเวอร์ชัน UUID เฉพาะนี่คือ regexes ที่เกี่ยวข้อง

โปรดทราบว่าแตกต่างเพียงอย่างเดียวคือหมายเลขรุ่นซึ่งจะอธิบายใน4.1.3. VersionบทของUUID 4122 RFC

หมายเลขเวอร์ชันเป็นอักขระตัวแรกของกลุ่มที่สาม[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

หากคุณใช้ Node.js เพื่อการพัฒนาขอแนะนำให้ใช้แพ็คเกจที่เรียกว่า Validator มันรวมถึง regexes ทั้งหมดที่จำเป็นในการตรวจสอบรุ่นที่แตกต่างกันของ UUID รวมทั้งคุณจะได้รับฟังก์ชั่นอื่น ๆ อีกมากมายสำหรับการตรวจสอบ

นี่คือลิงค์ npm: Validator

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

ที่น่าสนใจ แต่ดูเหมือนว่ามันคาดว่าจะมีเครื่องหมายขีดกลาง นี่คือ regexes สี่รายการที่ใช้อยู่ในปัจจุบัน - /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i และ / หรือ /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i และ / หรือ /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i / และ / หรือ /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i
ruffin

1
Validator รองรับเฉพาะ UUID v3-5 ไม่ใช่ v1
peteb

13

ข้างคำตอบ Gambol ของที่จะทำผลงานได้ในเกือบทุกกรณีคำตอบทั้งหมดที่อยู่พลาดเพื่อให้ห่างไกลว่าการจัดรูปแบบการจัดกลุ่ม (8-4-4-4-12) ไม่ได้บังคับให้guid ของการเข้ารหัสในข้อความ มันถูกใช้บ่อยมาก แต่เห็นได้ชัดว่าสายโซ่ธรรมดาของเลขฐานสิบหก 32 หลักสามารถใช้ได้ [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]คำถามที่เป็นเรื่องเกี่ยวกับการตรวจสอบไอเอ็นจีตัวแปร s ดังนั้นเราควรจะรวมถึงรูปแบบการใช้งานที่ไม่เป็นมิตรเช่นกัน


อันนี้ฉันชอบมาก ยิ่งไปกว่านั้น{?[0-9a-f]{8}-?[0-9a-f]{4}-?[1-5][0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}}?
ไมค์เนลสัน

10

regexes เฉพาะประเภททั้งหมดที่โพสต์จนถึงขณะนี้ล้มเหลวใน "ชนิด 0" ไม่มี UUID ที่กำหนดใน 4.1.7 ของ RFC เป็น:

nil UUID เป็นรูปแบบพิเศษของ UUID ที่ระบุว่ามี 128 บิตทั้งหมดตั้งค่าเป็นศูนย์: 00000000-0000-0000-0000-000000000000

หากต้องการแก้ไขคำตอบของ 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

หรือหากต้องการยกเว้น "ประเภท 0" โดยไม่ต้องมีศูนย์ทั้งหมดเรามีสิ่งต่อไปนี้ (ขอบคุณลุค):

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

ส่วน UUID แรกของศูนย์ UUID ควรมี 8 ศูนย์ไม่ใช่ 7 ส่วน regex ที่ให้ไว้ไม่ได้ตรวจสอบกับ 7
Rich Seviora

2
ของคุณดูดีกว่า แต่อนุญาต UUID ที่ไม่ถูกต้องเช่น: abcdef00-0000-0000-0000-000000000000 จะจับคู่ regex ของคุณ regex นี้จะตรงกับ UUID ที่ถูกต้องรวมถึงศูนย์:/^(?:[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
ลุค

10

ขอบคุณ @usertatha ที่มีการดัดแปลงบางอย่าง

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

ฉันคิดว่าคำตอบของ Gambolนั้นเกือบจะสมบูรณ์แบบ แต่มันตีความตีความRFC 4122 § 4.1.1 ผิด ส่วนตัวแปรเล็กน้อย

มันครอบคลุม Variant-1 UUIDs (10xx = 8..b) แต่ไม่ครอบคลุม Variant-0 (0xxx = 0..7) และ Variant-2 (110x = c..d) รุ่นที่สงวนไว้สำหรับความเข้ากันได้แบบย้อนหลัง ดังนั้นมันจึงเป็น UUID ที่ถูกต้องทางเทคนิค Variant-4 (111x = e..f) ถูกสงวนไว้สำหรับใช้ในอนาคตดังนั้นจึงไม่สามารถใช้งานได้ในปัจจุบัน

นอกจากนี้ประเภท 0 ไม่ถูกต้องว่า "หลัก" ได้รับอนุญาตให้เป็น 0 เท่านั้นหากเป็น NIL UUID (เช่นที่กล่าวถึงในคำตอบของ Evan )

ดังนั้นฉันคิดว่า regex ที่แม่นยำที่สุดที่สอดคล้องกับข้อกำหนด RFC 4122 ปัจจุบันคือ (รวมถึงเครื่องหมายขีดคั่น):

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

ใช้วิธี. match () เพื่อตรวจสอบว่า String เป็น 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}$");
}

Uncaught TypeError: s.matches ไม่ใช่ฟังก์ชั่น
Deep Kakkar

1
สคริปต์ที่กำหนดไม่ใช่ Javascript ซึ่งเป็นสิ่งที่ OP ร้องขอ
StefanJanssen

ปรับคำตอบเพื่อแสดงความคิดเห็นด้านบน โซลูชันตอนนี้ทำงานตามที่คาดไว้
DeeZone

นั่นยังไม่ใช่ js
ktilcu

1

คำตอบข้างต้นรุ่นแก้ไขเล็กน้อยเขียนด้วยวิธีที่กระชับมากขึ้น สิ่งนี้จะตรวจสอบ GUID ใด ๆ ที่มียัติภังค์ สิ่งนี้จะสนับสนุนอักขระตัวพิมพ์ใหญ่และตัวพิมพ์เล็กซึ่งกลายเป็นแบบแผนโดยไม่คำนึงถึงข้อกำหนด:

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

กุญแจนี่คือส่วนที่ทำซ้ำด้านล่าง

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

ซึ่งเพียงทำซ้ำ 4 รูปแบบถ่าน 3 ครั้ง


1
A-fควรจะA-Fชอบโดย:/^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}\-){3})([0-9a-fA-F]{12})$/i
Deezone

หากคุณใช้งานเคส (/ i) ทำไมต้องทำซ้ำ AF แล้วเลือก AF?
นิมรอด

0

วิธีที่ดีในการทำ Node คือใช้ajvแพ็คเกจ ( 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

ฉันคิดว่าวิธีที่ดีกว่าคือการใช้วิธีการคงที่จาก String เพื่อหลีกเลี่ยงการแสดงผลปกติเหล่านั้น

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

ในทางกลับกัน

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

พ่น java.lang.IllegalArgumentException: สตริง UUID ไม่ถูกต้อง: x

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.