如何测试有效的UUID/GUID



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

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

目前,UUID在RFC4122中指定。一个经常被忽略的边缘情况是NIL UUID。下面的正则表达式考虑了这一点,并将返回NIL UUID的匹配项。请参见下面的UUID,它只接受非nil 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中适当的变体。

注意:大括号{}不是正则表达式。它们是一些系统和用法的产物。

易于修改以上正则表达式以满足原问题的要求。

提示:regex组/捕获

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

如果您想要检查或验证特定的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
    

regex to rescue

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

如果您正在使用Node.js进行开发,建议使用一个名为Validator的包。它包括验证不同版本的UUID所需的所有正则表达式,以及用于验证的各种其他函数。

下面是npm的链接:

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

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

的例子:

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

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

除了Gambol的答案在几乎所有情况下都能完成的工作之外,到目前为止给出的所有答案都忽略了分组格式(8-4-4-4-12)不是强制要求在文本中编码guid的。它的使用非常频繁,但显然,32个十六进制数字的普通链也是有效的。<一口>[1] regex <子>掺:

/^[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]这个问题是关于检查变量s的,所以我们也应该包括用户不友好的表单。

    为什么在。net GUID中有破折号?-堆栈溢出加上接受的应答
  • 测试并验证GUID (guide .us)
  • Guid。ToString方法(String) (MSDN)

到目前为止发布的所有特定类型的正则表达式都在"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包,您可以导入验证并将id传递给它

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

我认为Gambol的答案几乎是完美的,但它误解了RFC 4122§4.1.1。

它涵盖了变量-1 uuid (10xx = 8..b),但不包括变量-0 (0xxx = 0..7)和变量-2 (110x = c..d)变体,这些变体是为了向后兼容而保留的,所以它们在技术上是有效的uuid。变种-4 (111x = e..f)确实是为将来使用而保留的,所以它们目前是无效的。

同样,0类型无效,即"数字";只有当它是NIL UUID时才允许为0(就像Evan的回答中提到的那样)。

所以我认为符合当前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)

以上答案稍作修改,以更简洁的方式书写。这将验证任何带有连字符的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次

如果有人使用yup, JavaScript模式验证器库,这个功能可以通过下面的代码实现。

const schema = yup.object().shape({
   uuid: yup.string().uuid()
 });
 const isValid = schema.isValidSync({uuid:"string"});

使用.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}$");
}

在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

版本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)));

我添加了一个UUID验证器到Apache Commons validator。它还没有被合并,但是你可以在这里为它投票:

https://github.com/apache/commons-validator/pull/68

我有这个函数,但它本质上与接受的答案相同。

export default function isUuid(uuid: string, isNullable: boolean = false): boolean {
    return isNullable
        ? /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(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.test(uuid);
}

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

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

另一方面

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

抛出java.lang.IllegalArgumentException: Invalid UUID string: x

相关内容

  • 没有找到相关文章

最新更新