Normal ifade ile metinde UUID'leri arama


225

Normal ifadeler kullanarak metin bloklarında UUID'leri arıyorum. Şu anda tüm UUID'lerin 8-4-4-4-12 onaltılık basamaklı bir patttern izleyeceği varsayımına güveniyorum.

Herkes bu varsayımın geçersiz olacağı ve bazı UUID'leri kaçırmamı sağlayacak bir kullanım durumu düşünebilir mi?


6 yıl önceki bu soru, bir metin bloğunda kredi kartları bulmak için bir projede bana yardımcı olmaktı. Daha sonra, kredi kartlarını ararken UUID'lerin
Guy

4
UUID normal ifade kalıbı eşleştirmesi için yapılan bir arama beni bu yığın taşması gönderisine getirdi, ancak kabul edilen cevap aslında bir cevap değil. Ayrıca, sorunuzun altındaki yorumda sağladığınız bağlantı da kalıba sahip değil (bir şey eksik olmadıkça). Bunlardan biri kullandığınız bir şey mi?
Tass

Gönderdiğim bağlantıdan başlayarak tavşanların warren'lerini takip ederseniz GitHub'da sonunda kullandığım regex'e sahip olan bu çizgiye rastlayabilirsiniz. ( Bulmanın
Guy

1
Bu yanıtların hiçbiri, yalnızca geçerli RFC 4122 UUID'lerin tüm varyantları için tek bir normal ifade vermemektedir. Ama burada böyle bir cevap verildi gibi görünüyor: stackoverflow.com/a/13653180/421049
Garret Wilson

Yanıtlar:


41

Tanım gereği normal ifadenizin herhangi bir UUID'yi kaçırmamasını kabul ediyorum. Bununla birlikte, özellikle Microsoft'un Global Benzersiz Tanımlayıcılarını (GUID'ler) arıyorsanız, bir GUID için beş eşdeğer dize temsili olduğunu unutmayın:

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

3
Hangi durumlarda ilk model bulunur? Yani tireleri soyup GUID'i tireler olmadan döndüren bir .Net işlevi var mı?
Guy

1
MyGuid.ToString ("N") ile alabilirsiniz.
Panos

462

Uuid için normal ifade:

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

19
yap şunu [a-f0-9]! Onaltılık gibi! Normal ifadeniz (olduğu gibi) yanlış pozitifler döndürebilir.
exhuma

13
Bazı durumlarda bunu [a-fA-F0-9] veya [A-F0-9] yapmak isteyebilirsiniz.
Hans-Peter Störr

22
@ cyber-monk: [0-9a-f], anlam ve hız bakımından [a-f0-9] ve [0123456789abcdef] ile özdeştir, çünkü normal ifade her durumda onaltılı rakam bir durum tablosuna giriş. Bu nasıl işler içine bir giriş noktası için bkz en.wikipedia.org/wiki/Nondeterministic_finite_automaton
JesperSM

11
Bu çözüm pek doğru değil. RFC4122 başına geçersiz sürümü ve varyant karakterleri olan kimliklerle eşleşir. @Gajus'un çözümü bu konuda daha doğrudur. Ayrıca, RFC girişte büyük harf karakterlere izin verir, bu nedenle [AF] eklemek uygun olur.
broofa

4
@broofa, yalnızca RFC ile tutarlı UUID'lerle eşleşen herkese gerçekten ayarlandığınızı görüyorum. Ancak, bunu birçok kez belirtmeniz gerektiğinin, tüm UUID'lerin RFC sürümünü ve varyant göstergelerini kullanmayacağı konusunda sağlam bir gösterge olduğunu düşünüyorum. UUID tanımı en.wikipedia.org/wiki/Uuid#Definition , basit bir 8-4-4-4-12 örüntüsü ve 2 ^ 128 olasılık olduğunu belirtir. RFC bunun sadece bir alt kümesini temsil eder. Peki ne eşleştirmek istiyorsun? Alt küme mi, hepsi mi?
Bruno Bronosky

121

@ivelin: UUID'nin büyük harfleri olabilir. Yani ya dizeyi toLowerCase () yapmanız veya kullanmanız gerekecek:

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

Sadece bu ama yeterli temsilcisi yorum olurdu :)


22
Genellikle, kalıbı, kalıptan sonra bir i ile büyük / küçük harfe duyarsız olarak tanımlayarak bunu halledebilirsiniz, bu daha temiz bir kalıp yapar: / [0-9a-f] {8} - [0-9a-f] {4} - [0 -9a-f] {4} - [0-9a-f] {4} - [0-9a-f] {12} / i
Thomas Bindzus

@ThomasBindzus Bu seçenek tüm dillerde mevcut değildir. Bu yanıttaki orijinal desen Go'da benim için çalıştı. /.../iVersiyon yoktu.
Chris Redford

110

Sürüm 4 UUID'ler, xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx biçimindedir; burada x, herhangi bir onaltılık basamaktır ve y, 8, 9, A veya B'den biridir. Örn. F47ac10b-58cc-4372-a567-0e02b2c3d479.

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

Bu nedenle, bu teknik olarak daha doğrudur:

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

1
Az demek istediğini sanmıyorum.
Bruno Bronosky

9
[AF] 'yi de kabul etmeniz gerekiyor. RFC4122'nin 3. bölümü başına: 'Onaltılı değerler olan "a" ila "f" küçük harfli karakterler olarak girilir ve girdide büyük / küçük harfe duyarlı değildir . Ayrıca (:?8|9|A|B)muhtemelen biraz daha okunabilir[89aAbB]
broofa

1
@ Broofa'nın değişikliğini kopyalamanız gerekiyor; küçük harf A veya B'yi hariç tuttuğunuz için
22'de ELLIOTTCABLE

6
@elliottcable Ortamınıza bağlı olarak, i(büyük / küçük harfe duyarsız) bayrak kullanın.
Gajus

20
Sürüm 1 ila 3 ve 5'i reddediyorsunuz. Neden?
14:20

91

Belirli bir UUID sürümünü kontrol etmek veya doğrulamak istiyorsanız , karşılık gelen normal ifadeler aşağıda verilmiştir.

Tek farkın, UUID 4122 RFC4.1.3. Version bölümünde açıklanan sürüm numarası olduğuna dikkat edin .

Sürüm numarası üçüncü grubun ilk karakteridir [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

Desenler küçük harfler içermez. Ayrıca a-fher A-Fkapsamın yanında olmalıdır .
Paweł Psztyć

27
iBüyük harf duyarsız olarak düzenli ifade işaretleri onu sonunda.
johnhaley81

Bir desen değiştirici her zaman kullanılamaz. Örneğin, bir openapi tanımında, desen büyük / küçük harfe duyarlıdır
Stephane Janicaud

1
@StephaneJanicaud OpenAPI'de, formatdeğiştiriciyi UUID'leri test etmek için bir normal ifade kullanmak yerine "uuid" olarak ayarlayarak kullanmalısınız: swagger.io/docs/specification/data-models/data-types/#format
Ivan Gabriele

@IvanGabriele bahşiş için teşekkür ederim, bu sadece bir örnektir, herhangi bir büyük / küçük harf duyarsız kalıbı kontrol etmek istemediğinizde de aynı problemdir.
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

Gajus'un normal ifadesi, geçerli olsalar bile UUID V1-3 ve 5'i reddediyor.


1
Ancak geçersiz sürümlere (8 veya A gibi) ve geçersiz değişkenlere izin verir.
Brice

[89AB] [0-9a-f] 'deki AB'nin büyük harf ve izin verilen karakterlerin geri kalanının küçük harf olduğuna dikkat edin. Beni Python'da yakaladı
Tony Sepia

17

[\w]{8}(-[\w]{4}){3}-[\w]{12} çoğu durumda benim için çalıştı.

Ya da gerçekten spesifik olmak istiyorsanız [\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}.


3
\ W, en azından Java'da, _ ve onaltılık rakamlarla eşleştiğini belirtmek gerekir. \ W yerine \ p {XDigit} koymak, onaltılık basamakları eşleştirmek için tanımlanan POSIX sınıfı olduğu için daha uygun olabilir. Bu, diğer Unicode karakter kümelerini kullanırken bozulabilir.
oconnor0

1
@oconnor \wgenellikle "kelime karakterleri" anlamına gelir. Onaltılık basamaktan çok daha fazla eşleşir. Çözümünüz çok daha iyi. Veya uyumluluk / okunabilirlik için kullanabilirsiniz[a-f0-9]
exhuma

1
İşte bir normal ifade gibi görünen ve bu kalıplarla eşleşen bir dize: ancak geçersiz bir normal ifade: 2wtu37k5-q174-4418-2cu2-276e4j82sv19
Travis Stevens

@OleTraveler doğru değil, bir cazibe gibi çalışır. 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 Bu dize (2wt ...) geçersiz bir UUID, ancak bu yanıtta verilen desen, geçerli bir UUID olduğunu yanlış gösteren bir dize ile eşleşiyor. UUID'nin neden geçersiz olduğunu hatırlamıyorum çok kötü.
Travis Stevens

10

Python re'de, rakamsaldan büyük harfli alfa'ya yayılabilir. Yani..

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

Bu en basit Python UUID normal ifadesini yapar:

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

Bunların performansını karşılaştırmak için timeit kullanmak için okuyucuya bir egzersiz olarak bırakacağım.

Zevk almak. Pythonic ™ 'i saklayın!

NOT: Bu açıklıklar da eşleşecektir :;<=>?@', size yanlış pozitifler verebileceğinden şüpheleniyorsanız, kısayolu almayın. (Bunu yorumlarda belirttiğiniz için Oliver Aubert'e teşekkür ederiz.)


2
[0-F] gerçekten 0-9 ve AF ile eşleşecek, aynı zamanda ASCII kodu 57 (9 için) ve 65 (A için) arasında olan herhangi bir karakterle eşleşecektir, yani:; <=>? @ '.
Olivier Aubert

7
Bu nedenle, dikkate almak istediğiniz durumlar dışında yukarıda belirtilen kodu kullanmayın: =>;? <;: - <@ =: - @ =; = - @; @: -> == @?> =:? = @; geçerli bir UUID olarak :-)
Olivier Aubert

9

Tanım olarak, bir UUID, tanımladığınız gibi 5 grupta tirelerle ayrılmış 32 onaltılık basamaktır. Normal ifadenizle hiçbirini kaçırmamalısınız.

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


2
Doğru değil. RFC4122 sürüm basamağı için yalnızca [1-5] ve varyant basamağı için [89aAbB] izin verir.
broofa

7

Yani, Richard Bronosky'nin aslında bugüne kadar en iyi cevabı olduğunu düşünüyorum, ancak bence bunu biraz daha basit (veya en azından terser) yapmak için biraz yapabilirsiniz:

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

1
Hatta terser:re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){4}[0-9a-f]{8}', re.I)
Pedro Gimeno

6

C ++ için varyant:

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

5

OS X ile birlikte oluşturulan UUID uuidgeniçin normal ifade deseni

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

İle doğrulayın

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

3
$UUID_RE = join '-', map { "[0-9a-f]{$_}" } 8, 4, 4, 4, 12;

BTW, konumlardan birinde yalnızca 4'e izin verilmesi yalnızca UUIDv4 için geçerlidir. Ancak v4 varolan tek UUID sürümü değildir. Uygulamada da v1 ile tanıştım.


2

Posix normal ifadesi ( grep -E, MySQL, vb.) Kullanıyorsanız, bunu okumak ve hatırlamak daha kolay olabilir:

[[:xdigit:]]{8}(-[[:xdigit:]]{4}){3}-[[:xdigit:]]{12}

0

Bash için:

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

Örneğin:

$> 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

Büyük / -iküçük harfe duyarlı olmayan eşleme için grep seçeneğini eklemeniz gerekir .
Alastair Irvine
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.