我正在使用正则表达式在文本块中搜索uuid。目前,我依赖于所有uuid都遵循8-4-4-4-12十六进制数字模式的假设。
有人能想到这样一个用例吗?在这个用例中,这个假设是无效的,并且会导致我错过一些uuid。
根据定义,UUID是32个十六进制数字,用连字符分隔为5组,正如您所描述的那样。你不应该错过任何正则表达式。
http://en.wikipedia.org/wiki/Uuid#Definition
我同意根据定义,你的正则表达式不会遗漏任何UUID。然而,如果你特别搜索微软的全球唯一标识符(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}}"
[\w]{8}(-[\w]{4}){3}-[\w]{12}在大多数情况下为我工作。
[\w]{8}(-[\w]{4}){3}-[\w]{12}
或者如果你想要更具体的[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}。
[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}
uuid的正则表达式是:
[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
如果你想强制整个字符串来匹配这个正则表达式,你有时(你的匹配器API可能有一个方法)需要用^...$来包围上面的表达式
^...$
^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
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是任何十六进制数字,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}/
在python re中,你可以从数字到大写alpha。所以. .
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来比较它们的性能作为读者的练习。
注意:这些跨度也将匹配:;<=>?@',所以,如果你怀疑这可能会给你假阳性,不要走捷径。(感谢Oliver Aubert在评论中指出这一点。)
:;<=>?@'
所以,我认为Richard Bronosky给出了迄今为止最好的答案,但我认为你可以让它变得更简单(或至少更简洁):
re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}', 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];
/^[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,尽管它们是有效的。
$UUID_RE = join '-', map { "[0-9a-f]{$_}" } 8, 4, 4, 4, 12;
BTW,在一个位置上只允许4只对UUIDv4有效。 但是v4并不是唯一存在的UUID版本。 我在实践中也遇到过v1 .
对于在OS X上使用uuidgen生成的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}"
如果你想检查或验证指定UUID版本,这里有相应的正则表达式。
注意唯一的区别是版本号,它在Uuid 4122 RFC的4.1.3. Version章节中解释。
4.1.3. Version
版本号是第三组的第一个字符:[VERSION_NUMBER][0-9A-F]{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
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
如果使用Posix regex (grep -E, MySQL等),这可能更容易阅读&记住:
grep -E
[[:xdigit:]]{8}(-[[:xdigit:]]{4}){3}-[[:xdigit:]]{12}
编辑: Perl &PCRE口味也支持Posix字符类,所以这将与他们一起工作。对于这些,将(…)更改为非捕获子组(?:…)。
(…)
(?:…)
下面是工作的REGEX: https://www.regextester.com/99148
const regex = [0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}
想要给出我的贡献,因为我的regex涵盖了OP的所有情况,并正确地将组方法上的所有相关数据分组(你不需要post处理字符串来获得uuid的每个部分,这个regex已经为你获得了它)
([\d\w]{8})-?([\d\w]{4})-?([\d\w]{4})-?([\d\w]{4})-?([\d\w]{12})|[{0x]*([\d\w]{8})[0x, ]{4}([\d\w]{4})[0x, ]{4}([\d\w]{4})[0x, {]{5}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})
官方uuid图书馆使用以下正则表达式:
/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i
看到参考
概括一个例子,其中下划线也被适当地忽略,只允许字母数字值,模式为8-4-4-4-12。
^[^\W_]{8}(-[^\W_]{4}){4}[^\W_]{8}$
或
^[^\W_]{8}(-[^\W_]{4}){3}-[^\W_]{12}$
两者都给出相同的结果,但最后一个更易于阅读。我想推荐一个网站,在那里人们可以学习和测试正则表达式正确:https://regexr.com/