정규식을 사용하여 텍스트에서 UUID 검색


224

정규식을 사용하여 텍스트 블록에서 UUID를 검색하고 있습니다. 현재 모든 UUID가 8-4-4-4-12 16 진수 패턴을 따르는 것으로 가정하고 있습니다.

누구 든지이 가정이 유효하지 않아 UUID를 놓칠 수있는 유스 케이스를 생각할 수 있습니까?


6 년 전의이 질문은 텍스트 블록에서 신용 카드를 찾는 프로젝트를 도와주었습니다. 신용 카드를 검색 할 때 UUID가 야기한 뉘앙스를 설명하는 내 블로그 게시물에서 링크 된 코드를 오픈 소스로 열었습니다. guyellisrocks.com/2013/11/…
Guy

4
UUID 정규식 패턴 일치를 검색하면이 스택 오버플로 게시물로 이동했지만 실제로는 대답이 아닙니다. 또한 귀하의 질문 아래 의견에 제공 한 링크에는 패턴이 없습니다 (내가 뭔가 빠진 경우 제외). 이 답변 중 하나가 결국 사용했던 것입니까?
Tass

내가 게시 한 링크로 시작하는 링크의 토끼 워렌을 따르면 GitHub 에서이 라인을 발견 할 수 있습니다. (찾는 것이 어렵다는 것을 이해할 수 없습니다.) 그 코드와 그 파일이 당신을 도울 수 있습니다 : github.com/guyellis/CreditCard/blob/master/Company.CreditCard/…
Guy

1
이 답변 중 어느 것도 유효한 RFC 4122 UUID의 모든 변형에 대해 단일 정규식을 제공하지 않는 것 같습니다. : 같은 대답이 여기에 주어진 것처럼하지만 보인다 stackoverflow.com/a/13653180/421049
개럿 윌슨

답변:


41

나는 당신의 정규 표현식이 UUID를 놓치지 않는다는 것에 동의합니다. 그러나 특히 Microsoft의 GUID (Globally Unique Identifier)를 검색하는 경우 GUID에 대해 5 개의 동등한 문자열 표현이 있습니다.

"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
어떤 상황에서 첫 번째 패턴이 발견됩니까? 즉, 하이픈을 제거하거나 하이픈없이 GUID를 반환하는 .Net 함수가 있습니까?
Guy

1
myGuid.ToString ( "N")으로 얻을 수 있습니다.
Panos

462

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

19
그것을 확인하십시오 [a-f0-9]! 16 진수로! 정규식은 (있는 그대로) 오 탐지를 반환 할 수 있습니다.
exhuma

13
경우에 따라 [a-fA-F0-9] 또는 [A-F0-9]로 만들 수도 있습니다.
Hans-Peter Störr

22
@ cyber-monk : [0-9a-f]는 정규식이 어쨌든 상태 머신으로 바뀌고 각 16 진수가 상태 테이블에 입력하십시오. 작동 방식에 대한 진입 점은 en.wikipedia.org/wiki/Nondeterministic_finite_automaton
JesperSM

10
이 솔루션은 정확하지 않습니다. RFC4122에 따라 유효하지 않은 버전 및 변형 문자가있는 ID와 일치합니다. @Gajus의 솔루션은 그 점에서 더 정확합니다. 또한 RFC는 입력시 대문자를 허용하므로 [AF]를 추가하는 것이 적절합니다.
broofa

4
@broofa, RFC와 일치하는 UUID 와만 일치하는 모든 사람에게 실제로 설정되어 있음을 알았습니다. 그러나 나는 당신이 이것을 여러 번 지적해야한다는 사실은 모든 UUID가 RFC 버전과 변형 지표를 사용하지 않을 것이라는 견고한 지표라고 생각합니다. UUID 정의 en.wikipedia.org/wiki/Uuid#Definition 은 간단한 8-4-4-4-12 패턴과 2 ^ 128 가능성을 나타냅니다. RFC는 그 중 일부만을 나타냅니다. 그래서 당신은 무엇을 일치시키고 싶습니까? 하위 집합입니까, 아니면 모두입니까?
Bruno Bronosky

120

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

방금 이것을 언급했지만 충분하지 않은 담당자 :)


22
일반적으로 패턴 다음에 i를 사용하여 대소 문자를 구분하지 않고 패턴을 정의하여이를 처리 할 수 ​​있습니다. 그러면 패턴이 더 깔끔해집니다. / [0-9a-f] {8}-[0-9a-f] {4}-[0 -9a-f] {4}-[0-9a-f] {4}-[0-9a-f] {12} / i
Thomas Bindzus 2019

@ThomasBindzus이 옵션은 모든 언어에서 사용할 수 없습니다. 이 답변의 원래 패턴은 Go에서 나에게 효과적이었습니다. /.../i버전은하지 않았다.
Chris Redford

110

버전 4 UUID의 형식은 xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx입니다. 여기서 x는 16 진수이며 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}/

난 당신이 아즈를 의미한다고 생각하지 않습니다.
Bruno Bronosky

8
[AF]도 수락해야합니다. RFC4122의 섹션 3에 따라 : '16 진 값 "a"에서 "f"는 소문자로 출력되며 입력에서 대소 문자를 구분하지 않습니다 . 또한 다음 (:?8|9|A|B)과 같이 약간 더 읽기 [89aAbB]
쉽습니다.

1
@broofa의 수정 사항을 복사해야합니다. 귀하의 경우 소문자 A 또는 B를 제외합니다.
ELLIOTTCABLE

6
@elliottcable 환경에 따라 i(대소 문자 구분) 플래그 만 사용하십시오 .
Gajus

20
버전 1 ~ 3과 5를 거부하고 있습니다. 왜 그렇습니까?
iGEL

90

특정 UUID 버전 을 확인하거나 확인 하려면 해당 정규식이 있습니다.

참고 것이 유일한 차이점은 버전 번호 에 설명되어, 4.1.3. VersionUUID 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-fA-F범위 옆에 포함되어야합니다 .
Paweł Psztyć 2016 년

27
i경우를 구분와 같은 정규식 마크를 말에.
johnhaley81

패턴 수정자를 항상 사용할 수있는 것은 아닙니다. 예를 들어, openapi 정의에서 패턴은 대소 문자를 구분합니다
Stephane Janicaud

1
@StephaneJanicaud OpenAPI에서는 format정규식을 사용하여 UUID를 테스트하는 대신 "uuid"로 설정 하여 수정자를 사용해야합니다 . swagger.io/docs/specification/data-models/data-types/#format
Ivan Gabriele

팁에 대해 @IvanGabriele에게 감사드립니다. 단지 예일뿐입니다. 대소 문자를 구분하지 않는 패턴을 확인하지 않으려는 경우에도 동일한 문제입니다.
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의 정규 표현식은 UUID V1-3 및 5가 유효하더라도 거부합니다.


1
그러나 유효하지 않은 버전 (예 : 8 또는 A)과 유효하지 않은 변형을 허용합니다.
Brice

[89AB] [0-9a-f]의 AB는 대문자이며 허용되는 나머지 문자는 소문자입니다. 그것은 파이썬에서 나를 사로 잡았습니다
Tony Sepia

17

[\w]{8}(-[\w]{4}){3}-[\w]{12} 대부분의 경우 나를 위해 일했습니다.

또는 당신이 정말로 구체적이기를 원한다면 [\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}.


3
Java에서 \ w는 적어도 16 진수뿐만 아니라 _와 일치한다는 점에 주목할 가치가 있습니다. \ w를 \ p {XDigit}로 바꾸는 것이 16 진수와 일치하도록 정의 된 POSIX 클래스이므로 더 적합 할 수 있습니다. 다른 유니 코드 문자 집합을 사용할 때 중단 될 수 있습니다.
oconnor0

1
@oconnor는 \w일반적으로 "단어 문자"를 의미합니다. 16 진수보다 훨씬 더 많이 일치합니다. 귀하의 솔루션이 훨씬 좋습니다. 또는 호환성 / 가독성을 위해 사용할 수 있습니다[a-f0-9]
exhuma

1
여기에 정규식 같은 외모와 그 패턴과 일치하는 문자열입니다,하지만 잘못된 정규식 : 2wtu37k5 - q174-4418-2cu2-276e4j82sv19
트래비스 스티븐스

@OleTraveler는 사실이 아니며 매력처럼 작동합니다. 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 해당 문자열 (2wt ...)은 잘못된 UUID이지만이 답변에 제공된 패턴은 해당 문자열이 유효한 UUID임을 잘못 나타내는 문자열과 일치합니다. UUID가 왜 유효하지 않은지 기억이 나지 않습니다.
트래비스 스티븐스

10

python re에서는 숫자에서 대문자로 확장 할 수 있습니다. 그래서..

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 정규식을 만듭니다.

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

나는 이것의 성능을 비교하기 위해 timeit을 사용하기 위해 독자에게 연습으로 남겨 두겠습니다.

즐겨. Pythonic ™ 유지하십시오!

참고 :이 범위도 일치 :;<=>?@'하므로 오 탐지 가능성이 있다고 생각되면 바로 가기를 사용하지 마십시오. (댓글에서 지적 해 주신 Oliver Aubert에게 감사합니다.)


2
[0-F]는 실제로 0-9 및 AF와 일치하지만 ASCII 코드가 57 (9) ~ 65 (A) 인 모든 문자는 :; <=>? @ '입니다.
Olivier Aubert

7
따라서 고려할 경우를 제외하고 위에서 언급 한 코드를 사용하지 마십시오. : =>;? <; :-<@ = :-@ =; =-@; @ :-> == @?> = :? = @; 유효한 UUID로 :-)
Olivier Aubert

9

정의에 따르면 UUID는 설명 된 것처럼 16 개의 16 진수 32 개이며 하이픈으로 5 개의 그룹으로 구분됩니다. 정규식을 놓치지 마십시오.

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


2
정확하지 않습니다. RFC4122는 버전 숫자에는 [1-5], 변형 숫자에는 [89aAbB] 만 허용합니다.
broofa

6

따라서 Richard Bronosky는 실제로 현재까지 가장 좋은 답변을 가지고 있다고 생각하지만 조금 더 간단하게 (또는 적어도 더 간결하게) 만들 수 있다고 생각합니다.

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

1
심지어 터져 :re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){4}[0-9a-f]{8}', re.I)
페드로 지 메노

5

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

5

로 OS X에서 생성 된 UUID의 uuidgen경우 정규식 패턴은 다음과 같습니다.

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

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

위치 중 하나에 4 만 허용하는 BTW는 UUIDv4에만 유효합니다. 그러나 v4가 존재하는 유일한 UUID 버전은 아닙니다. 실습에서도 v1을 만났습니다.


1

Posix 정규식 ( grep -E, MySQL 등)을 사용하는 경우 다음을 읽고 기억하기가 더 쉬울 수 있습니다.

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

0

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

예를 들면 다음과 같습니다.

$> 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.