我正在使用正则表达式在文本块中搜索UUID。目前,我所基于的假设是,所有UUID都将遵循8-4-4-4-12十六进制数字的样式。
谁能想到一个用例,这个假设将是无效的,并且会导致我错过一些UUID?
我正在使用正则表达式在文本块中搜索UUID。目前,我所基于的假设是,所有UUID都将遵循8-4-4-4-12十六进制数字的样式。
谁能想到一个用例,这个假设将是无效的,并且会导致我错过一些UUID?
Answers:
我同意,根据定义,您的正则表达式不会丢失任何UUID。但是,可能需要注意的是,如果要特别搜索Microsoft的全球唯一标识符(GUID),则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}}"
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
[a-f0-9]
!由于是十六进制!您的正则表达式(按原样)可能返回假阳性。
@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}
本来应该对此发表评论,但没有足够的代表:)
/.../i
版本没有。
版本4 UUID的格式为xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx,其中x是任何十六进制数字,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}/
(:?8|9|A|B)
可能更具可读性,例如[89aAbB]
i
(不区分大小写)标志。
如果要检查或验证特定的UUID版本,请参见以下相应的正则表达式。
请注意,唯一的区别是版本号,这在UUID 4122 RFC的
4.1.3. Version
章节中进行了说明。
版本号是第三组的第一个字符[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
范围旁边包含。
i
在正则表达式标记为不区分大小写的端部。
format
修饰符设置为“ uuid”来使用它,而不是使用正则表达式来测试UUID:swagger.io/docs/specification/data-models/data-types/#format
/^[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的regexp拒绝UUID V1-3和5,即使它们有效。
[\w]{8}(-[\w]{4}){3}-[\w]{12}
在大多数情况下为我工作。
或者,如果您想真正具体一点[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}
。
\w
通常表示“单词字符”,它将比十六进制数字匹配得多。您的解决方案要好得多。或者,出于兼容性/可读性的考虑,您可以使用[a-f0-9]
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')
在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™!
注意:这些跨度也将匹配,:;<=>?@'
因此,如果您怀疑这会给您带来误报,请不要使用快捷方式。(感谢奥利弗·奥伯特在评论中指出这一点。)
根据定义,UUID是32个十六进制数字,如前所述,由5个组用连字符分隔。您不应该错过任何正则表达式。
因此,我认为Richard Bronosky实际上是迄今为止最好的答案,但是我认为您可以做一些使其更简单(或至少更简短)的方法:
re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}', re.I)
re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){4}[0-9a-f]{8}', re.I)
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];