Recherche d'UUID dans le texte avec regex

224

Je recherche des UUID dans des blocs de texte à l'aide d'une expression régulière. Actuellement, je me fie à l'hypothèse que tous les UUID suivront un modèle de 8-4-4-4-12 chiffres hexadécimaux.

Quelqu'un peut-il penser à un cas d'utilisation où cette hypothèse serait invalide et me ferait manquer certains UUID?

Gars
la source
Cette question d'il y a 6 ans était pour m'aider dans un projet de recherche de cartes de crédit dans un bloc de texte. J'ai par la suite ouvert le code qui est lié à partir de mon article de blog qui explique la nuance que les UUID provoquaient lors de la recherche de cartes de crédit guyellisrocks.com/2013/11/…
Guy
4
Une recherche de correspondance d'expressions régulières UUID m'a amené à ce message de débordement de pile, mais la réponse acceptée n'est en fait pas une réponse. De plus, le lien que vous avez fourni dans le commentaire ci-dessous votre question n'a pas non plus le modèle (sauf si je manque quelque chose). L'une de ces réponses est-elle quelque chose que vous avez fini par utiliser?
Tass
Si vous suivez le dédale de lapin de liens commençant par celui que j'ai posté, vous pourriez rencontrer cette ligne dans GitHub qui a le regex que j'ai finalement utilisé. (Comprenant qu'il est difficile à trouver.) Ce code et ce fichier peuvent vous aider: github.com/guyellis/CreditCard/blob/master/Company.CreditCard/…
Guy
1
Aucune de ces réponses ne semble donner un seul regex pour toutes les variantes des seuls UUID RFC 4122 valides. Mais il semble qu'une telle réponse ait été donnée ici: stackoverflow.com/a/13653180/421049
Garret Wilson

Réponses:

41

Je suis d'accord que par définition, votre regex ne manque aucun UUID. Cependant, il peut être utile de noter que si vous recherchez en particulier les identificateurs globaux uniques (GUID) de Microsoft, il existe cinq représentations de chaînes équivalentes pour 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}}" 
Panos
la source
3
Dans quelles situations trouverait-on le premier schéma? Existe-t-il une fonction .Net qui supprimerait les tirets ou retournerait le GUID sans tirets?
Guy
1
Vous pouvez l'obtenir avec myGuid.ToString ("N").
Panos
462

Le regex pour uuid est:

\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b
Ivelin
la source
19
fais ça [a-f0-9]! Comme c'est hex! Votre regex (tel quel) pourrait retourner des faux positifs.
exhuma
13
Dans certains cas, vous pourriez même vouloir faire cela [a-fA-F0-9] ou [A-F0-9].
Hans-Peter Störr
22
@ cyber-moine: [0-9a-f] est identique à [a-f0-9] et [0123456789abcdef] en termes de sens et de vitesse, puisque l'expression régulière est de toute façon transformée en machine d'état, chaque chiffre hexadécimal étant transformé en un entrée dans une table d'état. Pour un point d'entrée sur la façon dont cela fonctionne, voir en.wikipedia.org/wiki/Nondeterministic_finite_automaton
JesperSM
10
Cette solution n'est pas tout à fait correcte. Il correspond aux ID qui ont des caractères de version et de variante non valides selon RFC4122. La solution de @Gajus est plus correcte à cet égard. En outre, le RFC autorise les caractères majuscules en entrée, donc l'ajout de [AF] serait approprié.
broofa
4
@broofa, je vois que vous êtes vraiment déterminé à ce que tout le monde ne corresponde qu'aux UUID compatibles avec le RFC. Cependant, je pense que le fait que vous ayez dû le souligner tant de fois est un indicateur solide que tous les UUID n'utiliseront pas les indicateurs de version et de variante RFC. La définition d'UUID en.wikipedia.org/wiki/Uuid#Definition indique un modèle 8-4-4-4-12 simple et 2 ^ 128 possibilités. Le RFC ne représente qu'un sous-ensemble de cela. Alors, que voulez-vous faire correspondre? Le sous-ensemble, ou tous?
Bruno Bronosky
120

@ivelin: UUID peut avoir des majuscules. Vous devrez donc soit toLowerCase () la chaîne ou utiliser:

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

Aurait juste commenté cela mais pas assez de représentants :)

Matthew F. Robben
la source
22
Habituellement, vous pouvez gérer cela en définissant le modèle comme insensible à la casse avec un i après le modèle, cela rend un modèle plus propre: / [0-9a-f] {8} - [0-9a-f] {4} - [0 -9a-f] {4} - [0-9a-f] {4} - [0-9a-f] {12} / i
Thomas Bindzus
@ThomasBindzus Cette option n'est pas disponible dans toutes les langues. Le modèle original de cette réponse a fonctionné pour moi dans Go. La /.../iversion ne l'a pas fait.
Chris Redford
110

Les UUID de la version 4 ont la forme xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx où x est un chiffre hexadécimal et y est l'un des 8, 9, A ou B. Par exemple f47ac10b-58cc-4372-a567-0e02b2c3d479.

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

C'est donc techniquement plus correct:

/[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}/
Gajus
la source
Je ne pense pas que tu veux dire az.
Bruno Bronosky
8
Vous devez également accepter [AF]. Selon la section 3 de la RFC4122: «Les valeurs hexadécimales« a »à« f »sont sorties en minuscules et ne respectent pas la casse en entrée ». Est également (:?8|9|A|B)probablement un peu plus lisible[89aAbB]
broofa
1
Besoin de copier la modification de @ broofa; car le vôtre exclut les minuscules A ou B.
ELLIOTTCABLE
6
@elliottcable Selon votre environnement, utilisez simplement l' iindicateur (insensible à la casse).
Gajus
20
Vous rejetez les versions 1 à 3 et 5. Pourquoi?
iGEL
90

Si vous souhaitez vérifier ou valider une version UUID spécifique , voici les expressions rationnelles correspondantes.

Notez que la seule différence est le numéro de version , qui est expliqué dans le 4.1.3. Versionchapitre de l' UUID 4122 RFC .

Le numéro de version est le premier caractère du troisième groupe [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
la source
Les modèles ne comprennent pas de lettres minuscules. Il doit également contenir à a-fcôté de chaque A-Fportée.
Paweł Psztyć
27
Le ià la fin de l'expression régulière le marque comme insensible à la casse.
johnhaley81
Un modificateur de motif ne peut pas toujours être utilisé. Par exemple, dans une définition openapi, le modèle est sensible à la casse
Stephane Janicaud
1
@StephaneJanicaud Dans OpenAPI, vous devriez plutôt utiliser le formatmodificateur en le définissant sur "uuid" au lieu d'utiliser une expression régulière
Ivan Gabriele
Merci @IvanGabriele pour l'astuce, ce n'était qu'un exemple, c'est le même problème lorsque vous ne voulez vérifier aucun modèle insensible à la casse.
Stephane Janicaud
35
/^[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'expression régulière de Gajus rejette les UUID V1-3 et 5, même si elles sont valides.

iGEL
la source
1
Mais il permet des versions invalides (comme 8 ou A) et des variantes invalides.
Brice
Notez que AB dans [89AB] [0-9a-f] est en majuscules et le reste des caractères autorisés sont en minuscules. Il m'a rattrapé en Python
Tony Sepia
17

[\w]{8}(-[\w]{4}){3}-[\w]{12} a travaillé pour moi dans la plupart des cas.

Ou si vous voulez être vraiment précis [\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}.

JimP
la source
3
Il convient de noter que \ w, en Java au moins, correspond à _ ainsi qu'aux chiffres hexadécimaux. Remplacer le \ w par \ p {XDigit} peut être plus approprié car c'est la classe POSIX définie pour faire correspondre les chiffres hexadécimaux. Cela peut se casser lors de l'utilisation d'autres jeux de caractères Unicode.
oconnor0
1
@oconnor \wsignifie généralement "caractères de mot". Il correspondra bien plus que les chiffres hexadécimaux. Votre solution est bien meilleure. Ou, pour la compatibilité / lisibilité que vous pourriez utiliser[a-f0-9]
exhuma
1
Voici une chaîne qui ressemble à une expression régulière et qui correspond à ces modèles, mais qui n'est pas une expression régulière valide: 2wtu37k5-q174-4418-2cu2-276e4j82sv19
Travis Stevens
@OleTraveler n'est pas vrai, fonctionne comme un charme. 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')
Tomasz Wojcik
3
@tom Cette chaîne (2wt ...) est un UUID non valide, mais le modèle donné dans cette réponse correspond à cette chaîne indiquant faussement qu'il s'agit d'un UUID valide. C'est dommage, je ne me souviens pas pourquoi cet UUID n'est pas valide.
Travis Stevens
10

Dans python re, vous pouvez s'étendre du numérique au alpha majuscule. Alors..

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

Cela fait l'expression rationnelle UUID Python la plus simple:

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

Je laisserai au lecteur le soin d'utiliser timeit pour comparer les performances de ceux-ci.

Prendre plaisir. Gardez-le Pythonic ™!

REMARQUE: ces plages correspondent également :;<=>?@'. Si vous pensez que cela pourrait vous donner de faux positifs, ne prenez pas le raccourci. (Merci Oliver Aubert de l'avoir signalé dans les commentaires.)

Bruno Bronosky
la source
2
[0-F] correspondra en effet à 0-9 et AF, mais aussi à tout caractère dont le code ASCII est compris entre 57 (pour 9) et 65 (pour A), c'est-à-dire n'importe lequel de:; <=>? @ '.
Olivier Aubert
7
N'utilisez donc pas le code susmentionné sauf si vous souhaitez prendre en compte: =>;? <;: - <@ =: - @ =; = - @; @: -> == @?> =:? = @; comme UUID valide :-)
Olivier Aubert
9

Par définition, un UUID est composé de 32 chiffres hexadécimaux, séparés en 5 groupes par des tirets, comme vous l'avez décrit. Vous ne devriez pas en manquer avec votre expression régulière.

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

pix0r
la source
2
Pas correcte. RFC4122 n'autorise que [1-5] pour le chiffre de la version et [89aAbB] pour le chiffre de la variante.
broofa
6

Donc, je pense que Richard Bronosky a en fait la meilleure réponse à ce jour, mais je pense que vous pouvez faire un peu pour le rendre un peu plus simple (ou au moins terser):

re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}', re.I)
Christopher Smith
la source
1
Même terser:re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){4}[0-9a-f]{8}', re.I)
Pedro Gimeno
5

Variante pour 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];
Anton K
la source
5

Pour les UUID générés sur OS X avec uuidgen, le modèle d'expression régulière est

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

Vérifiez avec

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}"
Quanlong
la source
2
$UUID_RE = join '-', map { "[0-9a-f]{$_}" } 8, 4, 4, 4, 12;

BTW, autorisant seulement 4 sur l'une des positions n'est valable que pour UUIDv4. Mais la v4 n'est pas la seule version UUID qui existe. J'ai également rencontré la v1 dans ma pratique.

abufct
la source
1

Si vous utilisez l'expression rationnelle Posix ( grep -E, MySQL, etc.), cela peut être plus facile à lire et à mémoriser:

[[:xdigit:]]{8}(-[[:xdigit:]]{4}){3}-[[:xdigit:]]{12}
Walf
la source
0

Pour bash:

grep -E "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}"

Par exemple:

$> 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
asherbar
la source