ฉันกำลังค้นหา UUID ในกลุ่มข้อความโดยใช้ regex ขณะนี้ฉันอาศัยสมมติฐานที่ว่า UUID ทั้งหมดจะเป็นไปตามรูปแบบเลขฐานสิบหก 8-4-4-4-12 เลขฐานสิบหก
ใครสามารถคิดกรณีการใช้งานที่สมมติฐานนี้จะไม่ถูกต้องและจะทำให้ฉันพลาด UUID บาง
ฉันกำลังค้นหา UUID ในกลุ่มข้อความโดยใช้ regex ขณะนี้ฉันอาศัยสมมติฐานที่ว่า UUID ทั้งหมดจะเป็นไปตามรูปแบบเลขฐานสิบหก 8-4-4-4-12 เลขฐานสิบหก
ใครสามารถคิดกรณีการใช้งานที่สมมติฐานนี้จะไม่ถูกต้องและจะทำให้ฉันพลาด UUID บาง
คำตอบ:
ฉันยอมรับว่าตามนิยาม regex ของคุณจะไม่พลาด UUID ใด ๆ อย่างไรก็ตามอาจมีประโยชน์ที่จะต้องทราบว่าหากคุณกำลังค้นหาตัวระบุที่ไม่ซ้ำกันทั่วโลกของ Microsoft (GUID) โดยเฉพาะมีการแสดงสตริงที่เทียบเท่าห้ารายการสำหรับ GUID:
"ca761232ed4211cebacd00aa0057b223"
"CA761232-ED42-11CE-BACD-00AA0057B223"
"{CA761232-ED42-11CE-BACD-00AA0057B223}"
"(CA761232-ED42-11CE-BACD-00AA0057B223)"
"{0xCA761232, 0xED42, 0x11CE, {0xBA, 0xCD, 0x00, 0xAA, 0x00, 0x57, 0xB2, 0x23}}"
regex สำหรับ uuid คือ:
\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b
[a-f0-9]
! มันเป็นฐานสิบหก! regex ของคุณ (ตามเดิม) สามารถส่งคืนผลบวกปลอม
@ivelin: UUID สามารถมีตัวพิมพ์ใหญ่ได้ ดังนั้นคุณจะต้อง toLowerCase () สตริงหรือใช้:
[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}
จะมีเพียงแค่แสดงความคิดเห็นนี้ แต่ตัวแทนไม่พอ :)
/.../i
รุ่นไม่ได้
UUID เวอร์ชัน 4 มีรูปแบบ xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx โดยที่ x เป็นเลขฐานสิบหกหลักใด ๆ และ y คือหนึ่งใน 8, 9, A หรือ B เช่น f47ac10b-58cc-4372-a567-0e02b2c3d479
แหล่งที่มา: http://en.wikipedia.org/wiki/Uuid#Definition
ดังนั้นนี่คือเทคนิคที่ถูกต้องมากขึ้น:
/[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}/
(:?8|9|A|B)
อาจอ่านได้มากขึ้นอีกด้วย[89aAbB]
i
แฟล็ก(ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่)
หากคุณต้องการตรวจสอบหรือตรวจสอบความถูกต้องของเวอร์ชัน 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
a-f
ถัดจากแต่ละA-F
ขอบเขต
i
ในตอนท้ายของเครื่องหมาย regex มันเป็นกรณีตาย
format
ตัวปรับเปลี่ยนโดยตั้งค่าเป็น "uuid" แทนที่จะใช้ regex เพื่อทดสอบ UUIDs: swagger.io/docs/specification/data-models/data-types/#format
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89AB][0-9a-f]{3}-[0-9a-f]{12}$/i
Gajus 'regexp ปฏิเสธ UUID V1-3 และ 5 แม้ว่ามันจะถูกต้องก็ตาม
[\w]{8}(-[\w]{4}){3}-[\w]{12}
ได้ทำงานให้ฉันในกรณีส่วนใหญ่
[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}
หรือถ้าคุณต้องการที่จะเฉพาะเจาะจงจริงๆ
\w
มักจะหมายถึง "คำตัวอักษร" มันจะตรงกับมากกว่าตัวเลขฐานสิบหก ทางออกของคุณดีขึ้นมาก หรือเพื่อความเข้ากันได้ / อ่านง่ายคุณสามารถใช้[a-f0-9]
import re def valid_uuid(uuid): regex = re.compile('[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}', re.I) match = regex.match(uuid) return bool(match) valid_uuid('2wtu37k5-q174-4418-2cu2-276e4j82sv19')
ในภาษาไพ ธ อนคุณสามารถขยายจากตัวเลขไปเป็นอัลฟาตัวพิมพ์ใหญ่ ดังนั้น..
import re
test = "01234ABCDEFGHIJKabcdefghijk01234abcdefghijkABCDEFGHIJK"
re.compile(r'[0-f]+').findall(test) # Bad: matches all uppercase alpha chars
## ['01234ABCDEFGHIJKabcdef', '01234abcdef', 'ABCDEFGHIJK']
re.compile(r'[0-F]+').findall(test) # Partial: does not match lowercase hex chars
## ['01234ABCDEF', '01234', 'ABCDEF']
re.compile(r'[0-F]+', re.I).findall(test) # Good
## ['01234ABCDEF', 'abcdef', '01234abcdef', 'ABCDEF']
re.compile(r'[0-f]+', re.I).findall(test) # Good
## ['01234ABCDEF', 'abcdef', '01234abcdef', 'ABCDEF']
re.compile(r'[0-Fa-f]+').findall(test) # Good (with uppercase-only magic)
## ['01234ABCDEF', 'abcdef', '01234abcdef', 'ABCDEF']
re.compile(r'[0-9a-fA-F]+').findall(test) # Good (with no magic)
## ['01234ABCDEF', 'abcdef', '01234abcdef', 'ABCDEF']
นั่นทำให้ Python UUID regex ที่ง่ายที่สุด:
re_uuid = re.compile("[0-F]{8}-([0-F]{4}-){3}[0-F]{12}", re.I)
ฉันจะปล่อยให้มันเป็นแบบฝึกหัดให้ผู้อ่านใช้ timeit เพื่อเปรียบเทียบประสิทธิภาพของสิ่งเหล่านี้
สนุก. เก็บ Pythonic ™!
หมายเหตุ:ช่วงเวลาเหล่านั้นจะตรงกัน:;<=>?@'
เช่นกันหากคุณสงสัยว่าอาจให้ผลบวกเป็นเท็จแก่คุณอย่าใช้ทางลัด (ขอบคุณ Oliver Aubert ที่ชี้ให้เห็นในความคิดเห็น)
ตามคำนิยาม UUID คือเลขฐานสิบหก 32 หลักคั่นด้วยเครื่องหมายยัติภังค์ 5 กลุ่มตามที่คุณอธิบายไว้ คุณไม่ควรพลาดอะไรกับการแสดงออกปกติของคุณ
ดังนั้นฉันคิดว่า Richard Bronosky มีคำตอบที่ดีที่สุดในปัจจุบัน แต่ฉันคิดว่าคุณสามารถทำได้เล็กน้อยเพื่อให้ง่ายขึ้น (หรืออย่างน้อย terer):
re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}', re.I)
re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){4}[0-9a-f]{8}', re.I)
ตัวแปรสำหรับ C ++:
#include <regex> // Required include
...
// Source string
std::wstring srcStr = L"String with GIUD: {4d36e96e-e325-11ce-bfc1-08002be10318} any text";
// Regex and match
std::wsmatch match;
std::wregex rx(L"(\\{[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}\\})", std::regex_constants::icase);
// Search
std::regex_search(srcStr, match, rx);
// Result
std::wstring strGUID = match[1];
สำหรับ UUID ที่สร้างบน OS X ด้วยuuidgen
รูปแบบ regex คือ
[A-F0-9]{8}-[A-F0-9]{4}-4[A-F0-9]{3}-[89AB][A-F0-9]{3}-[A-F0-9]{12}
ยืนยันด้วย
uuidgen | grep -E "[A-F0-9]{8}-[A-F0-9]{4}-4[A-F0-9]{3}-[89AB][A-F0-9]{3}-[A-F0-9]{12}"
$UUID_RE = join '-', map { "[0-9a-f]{$_}" } 8, 4, 4, 4, 12;
BTW ที่อนุญาตเพียง 4 ในตำแหน่งใดตำแหน่งหนึ่งเท่านั้นที่ใช้ได้สำหรับ UUIDv4 แต่ v4 ไม่ใช่รุ่น UUID เดียวที่มีอยู่ ฉันได้พบ v1 ในการฝึกฝนของฉันเช่นกัน
หากใช้ Posix regex ( grep -E
, MySQL, ฯลฯ ) การอ่านและจดจำอาจง่ายกว่า:
[[:xdigit:]]{8}(-[[:xdigit:]]{4}){3}-[[:xdigit:]]{12}
สำหรับทุบตี:
grep -E "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}"
ตัวอย่างเช่น:
$> echo "f2575e6a-9bce-49e7-ae7c-bff6b555bda4" | grep -E "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}"
f2575e6a-9bce-49e7-ae7c-bff6b555bda4