如何测试有效的 UUID/GUID?

410

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

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


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

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})

这个简单地将四个字符模式重复三次。


1
A-f should be A-F like so: /^([0-9a-fA-F]{8})-(([0-9a-fA-F]{4}\-){3})([0-9a-fA-F]{12})$/i - DeeZone
6
如果您忽略大小写(/i),为什么还要重复a-f和A-F? - Nimrod

4

我认为Gambol的答案几乎是完美的,但它对RFC 4122 § 4.1.1变体部分有一些误解。

它涵盖了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的答案中所述)。

因此,我认为最精确的正则表达式(包括连字符)符合当前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)

2
使用.match()方法来检查一个字符串是否为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}$");
}

未捕获的类型错误:s.matches不是一个函数。 - Deep Kakkar
2
给出的脚本不是JavaScript,这正是OP所要求的。 - StefanJanssen
根据上面的评论进行了调整,答案已经符合预期。 - DeeZone
4
那仍然不是JavaScript。 - ktilcu
@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}$' ); }; - Ahmed Aziz

2
在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 应该是 useDefault - tim
2
完成 - 如果您想要,现在可以删除您的评论。 - blackcatweb

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


0

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

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);
}

0

5
仅仅因为“Javascript”名称中包含“Java”,并不意味着它是一个Java问题。 - Thor Erik

-3

我认为更好的方法是使用静态方法 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


这个问题是关于Javascript的。这个答案在JS中也可用吗?这个异常看起来像是Java Exception。 - Joachim Rives

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