【问题标题】:How to determine if a string is a valid v4 UUID? [duplicate]如何确定字符串是否是有效的 v4 UUID? [复制]
【发布时间】:2013-11-14 22:10:41
【问题描述】:

我正在根据客户端浏览器生成的UUID 制作验证器,我用它来识别用户发送的某种类型的数据;并想验证客户端发送的UUID 实际上是有效的Version 4 UUID

我找到了这个PHP preg_match UUID v4,它很接近但不是我要找的。我想知道是否存在类似于is_empty()strtodate() 的东西如果字符串无效发送FALSE

我可以基于正则表达式做,但我想要更原生的东西来测试它。

有什么想法吗?

2019 年 11 月 23 日编辑: 关于重复标签,虽然版主在技术上是正确的,但这个问题的制定是为了将 fibd 其他东西用于正则表达式(如果存在),其次是这个question 已成为 Pythoners 和 PHPers 的参考,并且有不同的答案/方法来解决问题,并且通常可以更好地解释他们的答案。这就是为什么我认为应该坚持这个问题

【问题讨论】:

  • 这个问题是针对 PHP 的,但是对于那些想要在 Python 中执行此操作的人来说,下面的第二个答案非常好。

标签: php regex uuid


【解决方案1】:

版本 4 UUID 的格式为 xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx,其中 x 是任何十六进制数字,y89AB 之一。

^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$

要允许小写字母,请使用 i 修饰符 →

$UUIDv4 = '/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i';
preg_match($UUIDv4, $value) or die('Not valid UUID');

【讨论】:

  • 在执行正则表达式之前,我可能会添加一个简单的IF() 来测试字符串的长度是 32 还是 36 个字符。如果不是,则不是 UUID 十六进制字符串。
  • v4 UUID 的正确格式应包含破折号,因为它保留在答案中。 en.wikipedia.org/wiki/…
  • 如果不能使用 i 修饰符,可以使用^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89AB][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$
  • 如果不能使用修改的i,可以使用^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[ 0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$
【解决方案2】:

我在寻找 Python 答案时发现了这个问题。为了帮助处于相同情况的人们,我添加了 Python 解决方案。

您可以使用uuid 模块:

#!/usr/bin/env python

from uuid import UUID

def is_valid_uuid(uuid_to_test, version=4):
    """
    Check if uuid_to_test is a valid UUID.
    
     Parameters
    ----------
    uuid_to_test : str
    version : {1, 2, 3, 4}
    
     Returns
    -------
    `True` if uuid_to_test is a valid UUID, otherwise `False`.
    
     Examples
    --------
    >>> is_valid_uuid('c9bf9e57-1685-4c89-bafb-ff5af830be8a')
    True
    >>> is_valid_uuid('c9bf9e58')
    False
    """
    
    try:
        uuid_obj = UUID(uuid_to_test, version=version)
    except ValueError:
        return False
    return str(uuid_obj) == uuid_to_test


if __name__ == '__main__':
    import doctest
    doctest.testmod()

【讨论】:

  • 应该清楚的是,您所展示的不是 PHP,而这正是这个问题所要问的。因此,将这段代码放入并让它工作并不是一件容易的事,使用 PHP 中的 Python UUID 模块需要小心。
  • @Garbee 谢谢!我没有注意到这一点,因为我是通过 Google 提出这个问题的。显然,我没有仔细阅读这个问题。我仍然认为提出这个问题的人可能会对我的回答感兴趣。我明确表示我的答案是 Python 解决方案。
  • @jsbueno 不客气。我真的很喜欢这些 cmets,因为它们添加了额外的信息,并且 - 正如你所说 - 如果你不需要它们,它们可以被忽略:-)
  • 我绝不会要求您删除它们 - 我的目的是提醒任何使用它的人,如果没有这些,这是一个 4 班轮。但是,当我们这样做时 - 是否需要最后一行的比较?
  • @jsbueno 我其实不太确定。当我写这篇文章时,我认为这是必要的。如果我没记错的话,它与 UUID “修复”一些输入错误有关。但我必须再次查看 UUID 代码。
【解决方案3】:

所有现有答案都使用正则表达式。如果您使用的是 Python,您可能需要考虑使用try/except,以防您不想使用正则表达式: (比上面的答案短一点)。

我们的验证器将是:

import uuid

def is_valid_uuid(val):
    try:
        uuid.UUID(str(val))
        return True
    except ValueError:
        return False

>>> is_valid_uuid(1)
False
>>> is_valid_uuid("123-UUID-wannabe")
False
>>> is_valid_uuid({"A":"b"})
False
>>> is_valid_uuid([1, 2, 3])
False
>>> is_valid_uuid(uuid.uuid4())
True
>>> is_valid_uuid(str(uuid.uuid4()))
True
>>> is_valid_uuid(uuid.uuid4().hex)
True
>>> is_valid_uuid(uuid.uuid3(uuid.NAMESPACE_DNS, 'example.net'))
True
>>> is_valid_uuid(uuid.uuid5(uuid.NAMESPACE_DNS, 'example.net'))
True
>>> is_valid_uuid("{20f5484b-88ae-49b0-8af0-3a389b4917dd}")
True
>>> is_valid_uuid("20f5484b88ae49b08af03a389b4917dd")
True

【讨论】:

  • 注意 uuid.UUID() 接受的 UUID 语法变体:“{20f5484b-88ae-49b0-8af0-3a389b4917dd}”、“20f5484b88ae49b08af03a389b4917dd”
  • 感谢@PēterisCaune 很好的补充——.hex 的情况基本上涵盖了您添加的最后一个,但无论如何都值得添加。不知道“{uuid}”案例。
  • 这也是事实。 is_valid_uuid('-2b1eb780-8a03-4031-b1e5-2f7674c60df3') >> 是的
【解决方案4】:
import re

UUID_PATTERN = re.compile(r'^[\da-f]{8}-([\da-f]{4}-){3}[\da-f]{12}$', re.IGNORECASE)
uuid = '20f5484b-88ae-49b0-8af0-3a389b4917dd'

if UUID_PATTERN.match(uuid):
    return True
else:
    return False

【讨论】:

  • 也许你能解释一下?顺便说一句:return UUID_PATTERN.match(uuid)?
  • 其实是的,只是返回匹配更好。这里有什么不明白的地方?
  • @AndreyShipilov 可能他不明白为什么当问题要求 php 时你用 python 代码回答
  • 哈哈,其实我没注意到。
  • 顺便说一句——我测试了那个代码,发现 re.IGNORECASE 太贵了——应用 lower() 到 uuid 便宜得多
【解决方案5】:

如果您只是出于安全考虑需要它(例如,如果您需要在 javascript 代码中打印它并且您想避免 XSS),那么破折号的位置并不重要,所以它只是:

 /^[a-f0-9\-]{36}$/i

https://regex101.com/r/MDqB2Z/11


(它不是针对 v4 的,但通常一个编写良好的应用程序在删除破折号后将它们存储为 BINARY(16),因此如果出现问题,它将根本找不到对象并抛出 404,可能不需要过度验证)。

【讨论】:

  • 这没有回答问题。
  • 它确实回答了谁在寻找最简单的 uuid 验证
  • 这不会专门验证 UUID v4,因为它需要 4 和 [8-b] 在正确的位置。不过,确保正确的字符集很好。
猜你喜欢
  • 2011-09-09
  • 1970-01-01
  • 2021-12-08
  • 2012-11-27
  • 2015-05-23
  • 2011-01-11
  • 2012-04-02
  • 2023-03-21
  • 2011-03-26
相关资源
最近更新 更多