如何检查变量是否包含有效的 UUID/GUID 标识符?
我目前只对验证类型 1 和 4 感兴趣,但这不应该成为您答案的限制。
目前,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
如果您想检查或验证特定的 UUID 版本,这里是相应的正则表达式。
请注意,唯一的区别是版本号,在 4.1.3 中进行了说明。 UUID 4122 RFC 的版本章节。
版本号是第三组的第一个字符:[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
正则表达式来救援
/^[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-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/i
如果您使用 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
/^[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]/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
-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]/^[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]/^[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]/^[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]{12}$/i
感谢@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's answer 将在几乎所有情况下完成工作之外,到目前为止给出的所有答案都忽略了分组格式 (8-4-4-4-12) 对 encode GUIDs in text 不是强制性的。它的使用非常频繁,但显然 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] 问题是关于检查变量的,所以我们也应该包括对用户不友好的表单。
为什么 .NET GUID 中有破折号? - 堆栈溢出加上接受的答案
测试和验证 GUID (guid.us)
Guid.ToString 方法(字符串)(MSDN)
{?[0-9a-f]{8}-?[0-9a-f]{4}-?[1-5][0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12}}?
如果你使用 uuid 包,这个包会带来一个布尔验证函数,它会告诉你一个 uuid 是否有效。
例子:
import { validate as isValidUUID } from 'uuid';
if (!isValidUUID(tx.originId)) {
return Promise.reject('Invalid OriginID');
}
到目前为止发布的所有类型特定的正则表达式都在“类型 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
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
如果您使用 uuid 包,您可以导入 validate 并将 id 传递给它
const { v4: uuidv4, validate } = require('uuid');
const { id } = request.params;
validate(id) ? true : false;
我认为 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)
如果有人使用 yup ,JavaScript 模式验证器库,可以使用以下代码实现此功能。
const schema = yup.object().shape({
uuid: yup.string().uuid()
});
const isValid = schema.isValidSync({uuid:"string"});
Property 'uuid' does not exist on type 'StringSchema<string>'.
它仍然对您有用吗?
以更简洁的方式编写的上述答案的略微修改版本。这将验证任何带有连字符的 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
在 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
使用 .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}$");
}
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}$' ); };
版本 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)); } } 返回假; } // 测试 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' , 'AAAAAAA-1111-1111-AAAG-111111111111', ]; valid.forEach(test => console.log("有效案例,结果:"+isUUID(test))); invalid.forEach(test => console.log("无效的情况,结果:"+isUUID(test)));
我向 Apache Commons Validator 添加了一个 UUID 验证器。它尚未合并,但您可以在这里投票:
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:无效的 UUID 字符串:x
[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}