正規表現によるテキスト内のUUIDの検索


224

正規表現を使用してテキストのブロックでUUIDを検索しています。現在、私はすべてのUUIDが8-4-4-4-12の16進数のパターンに従うとの仮定に依存しています。

この仮定が無効であり、一部のUUIDを見逃す原因となるユースケースを誰かが考えることができますか?


6年前からのこの質問は、テキストブロックでクレジットカードを検索するプロジェクトで私を助けることでした。私は、その後のUUIDは、クレジットカードを検索する際に引き起こしていたことニュアンスを説明し、私のブログの記事からリンクされているコードオープンソース化しましたguyellisrocks.com/2013/11/...
ガイ

4
UUID正規表現のパターンマッチングを検索すると、このスタックオーバーフローの投稿に移動しましたが、実際には、受け入れられた回答は回答ではありません。さらに、質問の下のコメントで提供したリンクにもパターンがありません(何か不足している場合を除きます)。これらの答えの1つは、あなたが最終的に使用したものですか?
Tass

あなたが私が投稿したものから始まるリンクのウサギのウォーレンをたどると、私が最後に使用した正規表現を持つGitHubのこの行に出くわすかもしれません。コードと、そのファイルはあなたを助けるかもしれない(それを見つけるのは困難であることは理解):github.com/guyellis/CreditCard/blob/master/Company.CreditCard/...
ガイ

1
これらの回答はどれも、有効なRFC 4122 UUIDのみのすべてのバリアントに単一の正規表現を与えるようには見えません。しかし、そのような答えがここに与えられたようです:stackoverflow.com/a/13653180/421049
Garret Wilson

回答:


41

定義により、正規表現はUUIDを見逃さないことに同意します。ただし、特にMicrosoftのグローバル一意識別子(GUID)を検索する場合、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関数はありますか?
ガイ

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]!ヘックスなので!正規表現は(そのまま)、誤検知を返す可能性があります。
exhuma '25

13
場合によっては、[a-fA-F0-9]または[A-F0-9]にすることもできます。
Hans-PeterStörr

22
@ cyber-monk:[0-9a-f]は[a-f0-9]および[0123456789abcdef]と同じです。これは、正規表現がいずれにせよステートマシンに変換され、各16進数字が状態テーブルのエントリ。これがどのように機能するかのエントリポイントについては、en.wikipedia.org
wiki / Nondeterministic_finite_automaton

10
この解決策は正確ではありません。これは、RFC4122に従って無効なバージョンおよびバリアント文字を持つIDと一致します。@Gajusのソリューションはその点でより正確です。また、RFCでは入力時に大文字を使用できるため、[AF]を追加するのが適切です。
ブローファ2013

4
@broofa、私はあなたが本当にRFCと一貫性のあるUUIDだけにマッチするすべての人に設定されていることを知っています。ただし、これを何度も指摘しなければならなかったという事実は、すべてのUUIDがRFCバージョンとバリアントインジケーターを使用するわけではないという確かなインジケーターだと思います。UUID定義en.wikipedia.org/wiki/Uuid#Definitionは、単純な8-4-4-4-12パターンと2 ^ 128の可能性を示しています。RFCはそのサブセットのみを表しています。それであなたは何を一致させたいですか?サブセットですか、それともすべてですか?
Bruno Bronosky 2013

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

@ThomasBindzusこのオプションはすべての言語で使用できるわけではありません。この回答の元のパターンはGoで私に役立ちました。/.../iバージョンはしませんでした。
フォード

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

私はあなたがazを意味するとは思わない。
Bruno Bronosky 2013

8
[AF]も受け入れる必要があります。RFC4122のセクション3に従って:'16進値 "a"から "f"は小文字として出力され、入力では大文字と小文字が区別されません。また(:?8|9|A|B)、おそらく次のように少し読みやすくなります[89aAbB]
broofa

1
@broofaの変更をコピーする必要があります。あなたの除外は、AまたはBの場合の低下として
ELLIOTTCABLE

6
@elliottcable環境に応じて、i(大文字と小文字を区別しない)フラグを使用します。
Gajus 2014年

20
バージョン1から3および5を拒否します。なぜですか?
iGEL 2014年

90

特定のUUIDバージョンを確認または検証する場合は、対応する正規表現を以下に示します。

なお、唯一の違いは、バージョン番号に説明され、4.1.3. Versionの章UUID 4122 RFCは

バージョン番号は、3番目のグループの最初の文字です[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スコープの隣にも含める必要があります。
パヴェルPsztyć

27
iケース・小文字を区別しないように正規表現マークそれの終わりに。
johnhaley81 2017年

パターン修飾子は常に使用できるわけではありません。たとえば、openapi定義では、パターンは大文字と小文字が区別されます
Stephane Janicaud

1
@StephaneJanicaud OpenAPIではformat、正規表現を使用してUUIDをテストする代わりに、修飾子を「uuid」に設定して修飾子を使用する必要があります。swagger.io
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など)および無効なバリアントを許可します。
ブライス2018

[89AB] [0-9a-f]のABは大文字で、残りの許可された文字は小文字であることに注意してください。Pythonで私を見つけました
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クラスであるため、より適切な場合があります。他のUnicode文字セットを使用すると、これが壊れる可能性があります。
oconnor0

1
@oconnor \wは通常「単語の文字」を意味します。16進数よりもはるかに多く一致します。あなたのソリューションははるかに優れています。または、互換性/読みやすさのために使用できます[a-f0-9]
exhuma

1
これは、正規表現のように見え、それらのパターンに一致する文字列ですが、無効な正規表現です。2wtu37k5-q174-4418-2cu2-276e4j82sv19
Travis Stevens

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

3
@tomその文字列(2wt ...)は無効なUUIDですが、この回答で与えられたパターンはその文字列と一致し、有効なUUIDであることを誤って示しています。UUIDが無効である理由を思い出せません。
Travis Stevens

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、2015年

7
したがって、考慮したい場合を除いて、上記のコードを使用しないでください:=>;?<;:-<@ =:-@ =; =-@; @:-> == @?> =:?= @; 有効なUUIDとして:-)
Olivier Aubert


6

だから、私はリチャード・ブロノスキーが実際にこれまでのところ最高の答えを持っていると思いますが、それを少し単純にする(または少なくとももっと簡潔にする)ために少しすることができると思います:

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)
Pedro Gimeno

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;

ところで、位置の1つで4つだけを許可することは、UUIDv4に対してのみ有効です。ただし、存在するUUIDバージョンはv4だけではありません。私も私の実践でv1に会いました。


1

Posix regex(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.