【问题标题】:How to test valid UUID/GUID?如何测试有效的 UUID/GUID?
【发布时间】:2011-12-15 21:30:46
【问题描述】:

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

我目前只对验证类型 1 和 4 感兴趣,但这不应该限制您的答案。

【问题讨论】:

  • 字符串格式,不是十六进制,不是bin,或者我不知道你要什么
  • 如果您无法排除包含 32 个连续十六进制数字链的变量(不分组),请查看 my answer
  • 可能会有帮助:npmjs.com/package/uuid-validate

标签: javascript regex validation uuid guid


【解决方案1】:

版本 1 到 5,省略版本时不使用多版本正则表达式。

const uuid_patterns = {
  1: /^[0-9A-F]{8}-[0-9A-F]{4}-1[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
  2: /^[0-9A-F]{8}-[0-9A-F]{4}-2[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
  3: /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
  4: /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
  5: /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
};

const isUUID = (input, version) => {    
    if(typeof input === "string"){
        if(Object.keys(uuid_patterns).includes(typeof version === "string" ? version : String(version))){
            return uuid_patterns[version].test(input);
        } else {
            return Object.values(uuid_patterns).some(pattern => pattern.test(input));
        }
    }
    return false;
}

// Testing
let valid = [
    'A987FBC9-4BED-3078-CF07-9141BA07C9F3',
    'A987FBC9-4BED-4078-8F07-9141BA07C9F3',
    'A987FBC9-4BED-5078-AF07-9141BA07C9F3',
];

let invalid = [
    '',
    'xxxA987FBC9-4BED-3078-CF07-9141BA07C9F3',
    'A987FBC9-4BED-3078-CF07-9141BA07C9F3xxx',
    'A987FBC94BED3078CF079141BA07C9F3',
    '934859',
    '987FBC9-4BED-3078-CF07A-9141BA07C9F3',
    'AAAAAAAA-1111-1111-AAAG-111111111111',
];

valid.forEach(test => console.log("Valid case, result: "+isUUID(test)));
invalid.forEach(test => console.log("Invalid case, result: "+isUUID(test)));

【讨论】:

    【解决方案2】:

    如果你使用 uuid 包,你可以导入 validate 并将 id 传入其中

    const { v4: uuidv4, validate } = require('uuid');
    
    const { id } = request.params;
    validate(id) ? true : false;
    

    【讨论】:

      【解决方案3】:

      如果你使用 uuid 包,这个包会带来一个布尔验证函数,它会告诉你一个 uuid 是否有效。

      例子:

      import { validate as isValidUUID } from 'uuid';
      
      if (!isValidUUID(tx.originId)) {
        return Promise.reject('Invalid OriginID');
      }
      

      【讨论】:

      • 太棒了!对于我们这些已经在 J​​S 中生成 UUID 的人来说,这比公认的解决方案要好。
      • 是 2012 年的解决方案
      • 效果很好!!!
      【解决方案4】:

      在 Node 中执行此操作的一个好方法是使用 ajv 包 (https://github.com/epoberezkin/ajv)。

      const Ajv = require('ajv');
      const ajv = new Ajv({ allErrors: true, useDefaults: true, verbose: true });
      const uuidSchema = { type: 'string', format: 'uuid' };
      ajv.validate(uuidSchema, 'bogus'); // returns false
      ajv.validate(uuidSchema, 'd42a8273-a4fe-4eb2-b4ee-c1fc57eb9865'); // returns true with v4 GUID
      ajv.validate(uuidSchema, '892717ce-3bd8-11ea-b77f-2e728ce88125'); // returns true with a v1 GUID
      

      【讨论】:

      • 谢谢,你能更新你的答案中的一行吗,const ajv = new Ajv({ allErrors: true, useDefaults: true, verbose: true }); useDefaults not useDefault
      • 完成 - 如果需要,您现在可以删除您的评论。
      【解决方案5】:

      以更简洁的方式编写的上述答案的略微修改版本。这将验证任何带有连字符的 GUID(但是很容易修改以使连字符成为可选)。这也将支持无论规范如何都已成为惯例的大写和小写字符:

      /^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}\-){3})([0-9a-fA-F]{12})$/i
      

      这里的关键是下面的重复部分

      (([0-9a-fA-F]{4}\-){3})
      

      这只是将 4 个字符模式重复 3 次

      【讨论】:

      • A-f 应该是 A-F 就像这样:/^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}\-){3})([0-9a-fA-F]{12})$/i
      • 如果不区分大小写 (/i),为什么要重复 a-f 然后 A-F?
      【解决方案6】:

      使用.match()方法判断String是否为UUID。

      public boolean isUUID(String s){
          return 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}$");
      }
      

      【讨论】:

      • Uncaught TypeError: s.matches is not a function
      • 给定的脚本不是 Javascript,这是 OP 要求的。
      • 针对上述 cmets 的调整答案。解决方案现在按预期工作。
      • 那还不是js。
      • @ktilcu 这是在 JS 中 const isUUID = (uuid) => { return uuid.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}$' ); };
      【解决方案7】:

      我认为Gambol's answer 几乎是完美的,但它有点误解了RFC 4122 § 4.1.1. Variant section

      它涵盖 Variant-1 UUID (10xx = 8..b),但不涵盖 Variant-0 (0xxx = 0..7) 和 Variant-2 (110x = c..d) 变体向后兼容性,因此它们在技术上是有效的 UUID。 Variant-4 (111x = e..f) 确实保留供将来使用,因此它们目前无效。

      另外,0 类型是无效的,“数字”只有在它是 NIL UUID 时才允许为 0(如 Evan's answer 中提到的)。

      所以我认为符合当前 RFC 4122 规范的最准确的正则表达式是(包括连字符):

      /^([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[0-9a-d][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i
                                  ^                ^^^^^^
                          (0 type is not valid)  (only e..f variant digit is invalid currently)
      

      【讨论】:

        【解决方案8】:

        目前,UUID 是在 RFC4122 中指定的。一个经常被忽视的边缘情况是 NIL UUID,注意到here。以下正则表达式考虑了这一点,并将返回 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
        

        ...确保您有一个规范格式的 UUID,它是版本 1 到 5,并且是符合 RFC4122 的适当变体。

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

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

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

        为了避免匹配 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
        

        【讨论】:

        • 我认为 [1-5][0-9a-f]{3} 不正确。我有一个有效的 UUID,其中包含“b06a”,这对我来说失败了。
        • @FelipeBrahm,[1-5] 根据 RFC 是对的,4 位表示版本,只有 5 个版本。
        • 749d0000-0194-1005-2e05-08d61613bf2f 对我来说失败了
        • 出于好奇,(为什么)以下内容也无效:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
        • @mshaffer 第 21 行,第二个正则表达式定义似乎不正确,第一个没问题 - 验证空正则表达式和抢劫正则表达式,第二个 def 未能做到。
        【解决方案9】:

        我认为更好的方法是使用静态方法 fromString 来避免那些正则表达式。

            id = UUID.randomUUID();
            UUID uuid = UUID.fromString(id.toString());
            Assert.assertEquals(id.toString(), uuid.toString());
        

        另一方面

           UUID uuidFalse = UUID.fromString("x");
        

        抛出 java.lang.IllegalArgumentException:无效的 UUID 字符串:x

        【讨论】:

          【解决方案10】:

          感谢@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;
          }
          
          

          【讨论】:

          • 你可以使用 .test() 而不是 .match() 并返回它。
          【解决方案11】:

          到目前为止发布的所有类型特定的正则表达式都在“类型 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
          

          【讨论】:

          • nil UUID 的第一个 UUID 段应该有 8 个零,而不是 7。提供的正则表达式没有用 7 验证它。
          • 你的看起来更好,但允许一些无效的 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
          【解决方案12】:

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

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

          【讨论】:

          • 有趣的是,我有一个由 C# 创建的 Guid,它与其中任何一个都不匹配,因为它有一个“c”,正则表达式需要 8,9,A 或 B。
          【解决方案13】:

          除了Gambol's answer 几乎在所有情况下都可以完成这项工作,到目前为止给出的所有答案都错过了分组格式 (8-4-4-4-12) 对 @ 不是强制性的987654322@。它的使用非常频繁,但显然 32 位十六进制数字的普通链也是有效的。[1]regexenh

          /^[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}}?
          【解决方案14】:

          如果您使用 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
          

          【讨论】:

          • 很有趣,但它看起来需要连字符? Here are the four regexes it's currently using -- /^[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
          • 验证器只支持 UUID v3-5 不支持 v1
          【解决方案15】:

          正则表达式来救援

          /^[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}‌​\}?$/
          

          【讨论】:

          • 或者如果您可能有括号:/^\{?[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');
          • 这不太正确。它错过了 [1-5](版本)开始第 3 个块,而 [89AB](变体)开始第 4 个块。 Gambol's answer 做得对。
          • 更简洁的版本(忽略括号):/^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/i
          猜你喜欢
          • 2010-09-11
          • 2021-02-11
          • 2018-02-09
          • 1970-01-01
          • 2011-08-10
          相关资源
          最近更新 更多