如何测试有效的 UUID/GUID?

410

如何检查变量是否包含有效的UUID/GUID标识符?

我目前只关注验证类型1和4,但这不应限制你的答案。


以字符串格式返回已转换的文本内容,不要使用十六进制、二进制或其他你需要的格式。 - Marek Sebera
如果您无法排除包含32个连续十六进制数字(不分组)的变量,请查看我的答案 - Wolf
可能会有帮助:https://www.npmjs.com/package/uuid-validate - Ben
18个回答

585

目前,UUID遵循RFC4122规范。经常被忽视的边缘情况是NIL UUID,可以在这里找到。下面的正则表达式将考虑到这一点,并返回一个NIL UUID的匹配项。请参见下面只接受非NIL UUID的UUID。这两个解决方案都适用于版本1到5(参见第三个块的第一个字符)。

因此要验证UUID...

/^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i

确保您拥有符合RFC4122标准的规范格式化UUID,该UUID是版本1到5,并且是适当的变体。

注意:括号{}不是规范格式的。它们是一些系统和用法的产物。

很容易修改上述正则表达式以满足原始问题的要求。

提示:正则表达式组/捕获。

为避免匹配NIL UUID:

/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i

2
我认为 [1-5][0-9a-f]{3} 是不正确的。我有一个有效的 UUID,在那一部分中有“b06a”,但这对我来说是失败的。 - Felipe Brahm
1
@FelipeBrahm,根据RFC,[1-5]是正确的,4位表示版本,只有5个版本。 - rvignacio
1
749d0000-0194-1005-2e05-08d61613bf2f 在我的代码编辑环境中出现错误。 - robs
4
出于好奇,为什么以下内容不合法:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} - tjeerdnet
1
@jgozal 这是因为该UUID是伪UUID,不符合标准。 87f9 应该只以 [1-5] 开头,而 2977 应该只以 [ab89] 开头。在这里可以找到一个很好的解释:https://www.nearform.com/blog/new-crypto-capabilities-in-node-js/ - NeoNexus DeMortis
显示剩余2条评论

93

如果您想检查或验证特定的UUID版本,以下是相应的正则表达式。

请注意唯一的区别是版本号,该版本号在 UUID 4122 RFC 4.1.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
    

  • 1
    有趣的是,我有一个由C#创建的Guid,它不匹配其中任何一个,因为它在正则表达式期望8、9、A或B的位置上有一个"c"。 - ScubaSteve
    @ScubaSteve https://dev59.com/63VC5IYBdhLWcg3wlyIo和UUID之间有什么区别吗? - jcollum

    79

    正则表达式来拯救

    /^[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}$/.test('01234567-9ABC-DEF0-1234-56789ABCDEF0');
    
    或者用括号
    /^\{?[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}‌​\}?$/
    

    3
    如果您可能有括号:/^\{?[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}\}?$/.test('01234567-9ABC-DEF0-1234-56789ABCDEF0');此代码用于检查字符串是否符合指定格式,该格式为包含括号或不包含括号的标准 UUID(通用唯一标识符)格式。如果字符串符合该格式,则返回true。 - ryanb
    这不是完全正确的。它遗漏了 [1-5](版本)是第三块,[89AB](变体)是第四块。Gambol's answer 是正确的。 - Wolf
    11
    /^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/i 的更简洁版本。 - c24w

    58

    如果你在用Node.js进行开发,建议使用一个叫做 Validator 的包。它包含了验证不同版本的 UUID 所需的所有正则表达式,另外还提供了其他各种验证函数。

    以下是该包在npm上的链接:Validator

    var a = 'd3aa88e2-c754-41e0-8ba6-4198a34aa0a2'
    v.isUUID(a)
    true
    v.isUUID('abc')
    false
    v.isNull(a)
    false
    

    1
    有趣的是,它似乎期望使用连字符? 这里是它当前使用的四个正则表达式 - /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i 和/或 /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i 和/或 /^[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}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i - ruffin
    1
    验证器仅支持UUID v3-5,不支持v1。 - peteb

    46
    如果您使用uuid包,该包会提供一个布尔验证函数,用于告诉您UUID是否有效。
    示例:
    import { validate as isValidUUID } from 'uuid';
    
    if (!isValidUUID(tx.originId)) {
      return Promise.reject('Invalid OriginID');
    }
    

    3
    太棒了!对于我们已经在JS中生成UUID的人来说,比接受的解决方案更好。 - Damien
    这是一个2012年的解决方案。 - configbug
    非常好用!!! - Herii

    29

    感谢 @usertatha 的贡献,经过一些修改后得到了这个结果

    function isUUID ( uuid ) {
        let s = "" + uuid;
    
        s = s.match('^[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}$');
        if (s === null) {
          return false;
        }
        return true;
    }
    
    

    4
    你可以使用 .test() 代替 .match() 并直接返回结果。 - ScubaSteve
    请将文本从英文翻译成中文。只返回翻译后的文本内容:即 myRegex.test('test-uuid') 参见文档 - undefined

    15

    除了Gambol的回答几乎适用于所有情况,到目前为止给出的所有答案都忽略了分组格式(8-4-4-4-12)不是必须的,在文本中编码GUIDs。它被广泛使用,但显然32个十六进制数字的简单链也可以是有效的。[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
    

    [1]问题是关于检查变量的,因此我们也应该包含不太用户友好的形式。


    这是我的最爱。甚至更好的 {?[0-9a-f]{8}-?[0-9a-f]{4}-?[1-5][0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}}? - mike nelson
    1
    如果您使用RFC4122作为指南,必须包含连字符。其他一些来源(例如Microsoft)可能在某些地方使用无连字符的GUID。如果此答案想要讨论检查变量是否具有有效的128位值,则可以使用无限的方法将128位值编码为变量。此答案仅涉及一种变量编码,即32个十六进制字符的字符串,这不是RFC4122编码。我很遗憾不得不研究连字符是否可选。根据RFC4122,它们是必需的。 - Cameron

    11

    到目前为止,所有特定类型的正则表达式都未能匹配“type 0”Nil UUID。在RFC 4.1.7中定义了它:

      

    Nil UUID是UUID的一种特殊形式,它被指定为所有128位均设置为零:00000000-0000-0000-0000-000000000000

    修改Wolf的答案:

    /^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-5][0-9a-f]{3}-?[089ab][0-9a-f]{3}-?[0-9a-f]{12}$/i
    

    或者,为了正确地排除所有零而不是“类型0”,我们有以下方法(感谢Luke):

    /^(?:[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
    

    空 UUID 的第一个 UUID 段应该有 8 个零,而不是 7 个。提供的正则表达式没有验证它是否为 7 个。 - Rich Seviora
    2
    你的看起来更好,但允许一些无效的UUID,例如:abcdef00-0000-0000-0000-000000000000将匹配你的正则表达式。这个正则表达式将匹配有效的UUID,包括nil: /^(?:[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 - Luke

    9
    如果您使用uuid包,您可以导入validate并将id传递给它。
    const { v4: uuidv4, validate } = require('uuid');
    
    const { id } = request.params;
    validate(id) ? true : false;
    

    6
    如果有人使用JavaScript模式验证器库yup,可以使用以下代码实现此功能。
    const schema = yup.object().shape({
       uuid: yup.string().uuid()
     });
     const isValid = schema.isValidSync({uuid:"string"});
    

    我尝试这个时候收到了以下错误信息: “在类型为'StringSchema<string>'的对象上不存在属性'uuid'。”你还能正常使用吗? - Thomas Soos
    @ThomasSoos 你能分享一下你的代码片段吗? - NS23
    我尝试了你的代码片段... - Thomas Soos
    在 runkit 上尝试了这段代码 https://npm.runkit.com/yup ,对我仍然有效。 - NS23

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接