正規表現を使用してテキストブロックでUUIDを検索しています。現在、すべてのUUIDが8-4-4-4-12の16進数のパターンに従うという前提に依存しています。
この仮定が無効であり、いくつかのUUIDを見逃す原因となるユースケースを誰もが考えられますか?
定義により、正規表現が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}}"
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
@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}
これをコメントしただけだったが、十分な担当者ではなかった:)
バージョン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}/
特定のUUIDバージョンを確認または検証する場合は、対応する正規表現を次に示します。
唯一の違いはバージョン番号であることに注意してください。これは ID 4122 RFC の
4.1.3. Version
章で説明されています。
バージョン番号は、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
/^[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が有効であっても拒否します。
ほとんどの場合、[\w]{8}(-[\w]{4}){3}-[\w]{12}
が機能しました。
または、本当に特定の[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}
にしたい場合。
定義上、UUIDは32桁の16進数であり、説明したとおり、ハイフンで5つのグループに分けられます。正規表現をお見逃しなく。
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に感謝します。)
だから、リチャード・ブロノスキーが実際にこれまでのところ最良の答えを持っていると思うが、それを少し簡単にするために少しでもできると思う。
re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}', re.I)
OS Xでuuidgen
を使用して生成されたUUIDの場合、正規表現パターンは
[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}"
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];
$UUID_RE = join '-', map { "[0-9a-f]{$_}" } 8, 4, 4, 4, 12;
ところで、ポジションの1つで4のみを許可することは、UUIDv4に対してのみ有効です。ただし、存在するUUIDバージョンはv4だけではありません。練習でもv1に出会いました。