0

Корректное регулярное выражение для совпадения значений, сгенерированных uuid.uuid4().hex?

9

Вопрос: Как проверить, что значение соответствует UUID4, сгенерированному с помощью этого кода?

Я использую следующий код для генерации UUID4:

uuid.uuid4().hex

Убедитесь, что значение, которое я хочу проверить, является корректным UUID4. Является ли правильным решением использование регулярного выражения? Сгенерированные значения представляют собой 32-символьные строки в следующем формате:

60e3bcbff6c1464b8aed5be0fce86052

Как мне корректно выполнить валидацию этого значения в Python?

3 ответ(ов)

1

Как мне известно, ответ Мартина не является на 100% корректным. UUID версии 4 содержит пять групп шестнадцатеричных символов: первая группа состоит из 8 символов, вторая — из 4 символов, третья — из 4 символов, четвертая — из 4 символов и пятая — из 12 символов.

Однако для того, чтобы сделать его валидным UUID4, третья группа (которая находится посередине) должна начинаться с 4:

00000000-0000-4000-0000-000000000000
              ^

Кроме того, четвертая группа должна начинаться с 8, 9, a или b.

00000000-0000-4000-a000-000000000000
              ^    ^

Таким образом, вам необходимо изменить регулярное выражение Мартина на следующее:

import re
uuid4hex = re.compile('[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\Z', re.I)
0

Чтобы быть более конкретным. Вот самый точный регулярное выражение для захвата UUID версии 4 как с тире, так и без, которое соответствует всем правилам UUID4:

[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}

Вы можете убедиться, что оно также захватывает заглавные буквы, используя флаг игнорирования регистра. В моем примере используется re.I. (UUID не содержат заглавных букв в своем выводе, но во входных данных это не вызывает ошибок, просто игнорируется. Это значит, что в UUID "f" и "F" считаются одинаковыми).

Я создал валидатор для их проверки, который выглядит следующим образом:

import re

def valid_uuid(uuid):
    regex = re.compile('^[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}\Z', re.I)
    match = regex.match(uuid)
    return bool(match)

Теперь вы можете сделать так:

if valid_uuid(my_uuid):
    # Выполнить действия с валидным my_uuid

С помощью ^ в начале и \Z в конце я также убеждаюсь, что в строке нет ничего лишнего. Это гарантирует, что "3fc3d0e9-1efb-4eef-ace6-d9d59b62fec5" вернёт True, а "3fc3d0e9-1efb-4eef-ace6-d9d59b62fec5+19187" вернёт False.

Обновление - приведенный способ на Python не является надежным - смотрите комментарии:

Существуют и другие способы валидации UUID. В Python можно сделать так:

from uuid import UUID
try:
    UUID(my_uuid)
    # my_uuid валидный, и вы можете его использовать
except ValueError:
    # выполняйте нужные действия, когда my_uuid не является UUID
0

В качестве полезной заметки по вопросам производительности, я протестировал оба метода в терминах времени выполнения, и метод валидации с использованием регулярных выражений оказался немного быстрее:

import re
from uuid import UUID

def _validate_uuid4(uuid_string):
    try:
        UUID(uuid_string, version=4)
    except ValueError:
        return False
    return True

def _validate_uuid4_re(uuid_string):
    uuid4hex = re.compile('^[a-f0-9]{8}-?[a-f0-9]{4}-?4[a-f0-9]{3}-?[89ab][a-f0-9]{3}-?[a-f0-9]{12}\Z', re.I)
    match = uuid4hex.match(uuid_string)
    return bool(match)

Выполнив команды в ipython, я получил следующие результаты:

> In [58]: val = str(uuid.uuid4())
> In [59]: %time _validate_uuid4(val)
  CPU times: user 0 ns, sys: 0 ns, total: 0 ns
  Wall time: 30.3 µs
  Out[59]: True

> In [60]: %time _validate_uuid4_re(val)
  CPU times: user 0 ns, sys: 0 ns, total: 0 ns
  Wall time: 25.3 µs
  Out[60]: True

> In [61]: val = "invalid_uuid"
> In [62]: %time _validate_uuid4(val)
  CPU times: user 0 ns, sys: 0 ns, total: 0 ns
  Wall time: 29.3 µs
  Out[62]: False

> In [63]: %time _validate_uuid4_re(val)
  CPU times: user 0 ns, sys: 0 ns, total: 0 ns
  Wall time: 25.5 µs
  Out[63]: False

Как видно из результатов, метод с регулярными выражениями (_validate_uuid4_re) демонстрирует улучшенную производительность по сравнению с традиционным методом валидации UUID (_validate_uuid4). Это особенно заметно при проверке неверного UUID: время выполнения оба метода примерно одинаково, но метод с регулярными выражениями все же оказывается чуть быстрее.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь