Ricerca di UUID nel testo con espressioni regolari

Sto cercando UUID in blocchi di testo usando una regex. Attualmente sto facendo affidamento sul presupposto che tutti gli UUID seguiranno un tracciato di 8-4-4-4-12 cifre esadecimali.

Qualcuno può pensare a un caso d’uso in cui questa ipotesi non sarebbe valida e mi farebbe perdere alcuni UUID?

Sono d’accordo che, per definizione, la tua espressione regolare non perda nessun UUID. Tuttavia può essere utile notare che se si cercano in particolare gli identificatori univoci globali (GUID) di Microsoft, esistono cinque rappresentazioni di stringa equivalenti per un 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}}" 

Il regex per uuid è:

 [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} 

@ivelin: UUID può avere capitali. Quindi dovrai oLasciareCase () la stringa o usare:

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

Avrei appena commentato questo, ma non abbastanza rep 🙂

Gli UUID versione 4 hanno il formato xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx dove x è qualsiasi cifra esadecimale e y è uno tra 8, 9, A o B. es. F47ac10b-58cc-4372-a567-0e02b2c3d479.

fonte: http://en.wikipedia.org/wiki/Uuid#Definition

Pertanto, questo è tecnicamente più corretto:

 /[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}/ 

Se si desidera verificare o convalidare una specifica versione UUID , ecco le regex corrispondenti.

Si noti che l’unica differenza è il numero di versione , che è spiegato in 4.1.3. Version 4.1.3. Version capitolo di UUID 4122 RFC .

Il numero di versione è il primo carattere del terzo gruppo: [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 
 /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89AB][0-9a-f]{3}-[0-9a-f]{12}$/i 

L’espressione regolare di Gajus rifiuta UUID V1-3 e 5, anche se sono validi.

[\w]{8}(-[\w]{4}){3}-[\w]{12} ha funzionato per me nella maggior parte dei casi.

O se vuoi essere davvero specifico [\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12} .

Per definizione, un UUID è composto da 32 cifre esadecimali, separate in 5 gruppi da trattini, proprio come hai descritto. Non dovresti perdere nessuno con la tua espressione regolare.

http://en.wikipedia.org/wiki/Uuid#Definition

In python re, puoi spaziare da alfa numerico a maiuscolo. Così..

 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'] 

Questo rende la più semplice espressione regolare UUID Python:

 re_uuid = re.compile("[0-F]{8}-([0-F]{4}-){3}[0-F]{12}", re.I) 

Lascerò come esercizio al lettore l’uso del tempo per confrontare le prestazioni di questi.

Godere. Mantieni Pythonic ™!

NOTA: Quelle span corrisponderanno anche a:; < => :;< =>?@' Così, se si sospetta che possa darti dei falsi positivi, non prendere la scorciatoia. (Grazie Oliver Aubert per averlo indicato nei commenti.)

Quindi, penso che Richard Bronosky abbia effettivamente la migliore risposta fino ad oggi, ma penso che si possa fare un po ‘per renderlo un po’ più semplice (o almeno terser):

 re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}', re.I) 

Variante per C ++:

 #include  // 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]; 

Per UUID generato su OS X con uuidgen , lo schema regex è

 [A-F0-9]{8}-[A-F0-9]{4}-4[A-F0-9]{3}-[89AB][A-F0-9]{3}-[A-F0-9]{12} 

Verifica con

 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-z]{$_}" } 8, 4, 4, 4, 12; 

BTW, consentendo solo 4 su una delle posizioni è valido solo per UUIDv4. Ma v4 non è l’unica versione UUID esistente. Ho incontrato anche v1 nella mia pratica.