Поиск UUID в тексте с помощью регулярных выражений

Я ищу UUID в блоках текста с помощью регулярных выражений. В настоящее время я полагаюсь на предположение, что все UUID будут следовать шаблонам из 8-4-4-4-12 шестнадцатеричных цифр.

Кто-нибудь может вспомнить случай использования, когда это предположение было бы недействительным и заставило бы меня пропустить некоторые UUID?

20 ответов

Решение

Я согласен, что по определению ваше регулярное выражение не пропускает ни одного UUID. Однако может быть полезно отметить, что если вы ищете, в частности, глобальные уникальные идентификаторы (GUID) Microsoft, существует пять эквивалентных строковых представлений для GUID:

"ca761232ed4211cebacd00aa0057b223" 

"CA761232-ED42-11CE-BACD-00AA0057B223" 

"{CA761232-ED42-11CE-BACD-00AA0057B223}" 

"(CA761232-ED42-11CE-BACD-00AA0057B223)" 

"{0xCA761232, 0xED42, 0x11CE, {0xBA, 0xCD, 0x00, 0xAA, 0x00, 0x57, 0xB2, 0x23}}" 

Регулярное выражение для uuid:

\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b

@ivelin: UUID может иметь заглавные буквы. Поэтому вам нужно либо toLowerCase() строки, либо использовать:

[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}

Только что прокомментировал это, но не достаточно репутации:)

Если вы хотите проверить или проверить конкретную версию UUID, вот соответствующие регулярные выражения.

Обратите внимание, что единственным отличием является номер версии, который объясняется в 4.1.3. Version Глава 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
    

UUID версии 4 имеют форму xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, где x - любая шестнадцатеричная цифра, а y - одна из 8, 9, A или B. Например, f47ac10b-58cc-4372-a567-0e02b2c3d479.

источник: http://en.wikipedia.org/wiki/Uuid

Следовательно, это технически более правильно:

/[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}/
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89AB][0-9a-f]{3}-[0-9a-f]{12}$/i

Регулярное выражение Gajus отклоняет UUID V1-3 и 5, даже если они действительны.

[\w]{8}(-[\w]{4}){3}-[\w]{12} работал для меня в большинстве случаев.

Или если вы хотите быть действительно конкретным [\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12},

В python re, вы можете перейти от цифр до букв верхнего регистра. Так..

import re
test = "01234ABCDEFGHIJKabcdefghijk01234abcdefghijkABCDEFGHIJK"
re.compile(r'[0-f]+').findall(test) # Bad: matches all uppercase alpha chars
## ['01234ABCDEFGHIJKabcdef', '01234abcdef', 'ABCDEFGHIJK']
re.compile(r'[0-F]+').findall(test) # Partial: does not match lowercase hex chars
## ['01234ABCDEF', '01234', 'ABCDEF']
re.compile(r'[0-F]+', re.I).findall(test) # Good
## ['01234ABCDEF', 'abcdef', '01234abcdef', 'ABCDEF']
re.compile(r'[0-f]+', re.I).findall(test) # Good
## ['01234ABCDEF', 'abcdef', '01234abcdef', 'ABCDEF']
re.compile(r'[0-Fa-f]+').findall(test) # Good (with uppercase-only magic)
## ['01234ABCDEF', 'abcdef', '01234abcdef', 'ABCDEF']
re.compile(r'[0-9a-fA-F]+').findall(test) # Good (with no magic)
## ['01234ABCDEF', 'abcdef', '01234abcdef', 'ABCDEF']

Это делает простейшее регулярное выражение Python UUID:

re_uuid = re.compile("[0-F]{8}-([0-F]{4}-){3}[0-F]{12}", re.I)

Я оставлю это в качестве упражнения для читателя, чтобы использовать timeit для сравнения их производительности.

Наслаждаться. Держите это Pythonic™!

ПРИМЕЧАНИЕ. Эти промежутки также будут совпадать :;<=>?@' поэтому, если вы подозреваете, что это может дать вам ложные срабатывания, не используйте ярлык. (Спасибо, Оливер Обер, за то, что указал на это в комментариях.)

По определению UUID - это 32 шестнадцатеричные цифры, разделенные на 5 групп дефисами, как вы уже описали. Вы не должны пропустить ни одного со своим регулярным выражением.

http://en.wikipedia.org/wiki/Uuid

При использовании регулярного выражения Posix (grep -E, MySQL и т. Д.), Это может быть легче прочитать и запомнить:

[[:xdigit:]]{8}(-[[:xdigit:]]{4}){3}-[[:xdigit:]]{12}

Изменить: разновидности Perl и PCRE также поддерживают классы символов Posix, так что это будет работать с ними. Для тех, измените(…) к не захватывающей подгруппе (?:…).

Вот рабочий REGEX: https://www.regextester.com/99148

const regex = [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}

Итак, я думаю, что Ричард Броноски на самом деле имеет лучший ответ на сегодняшний день, но я думаю, что вы можете сделать немного, чтобы сделать его несколько проще (или, по крайней мере, более кратким):

re_uuid = re.compile(r'[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}', re.I)

Для UUID, сгенерированного на OS X с uuidgenшаблон регулярного выражения

[A-F0-9]{8}-[A-F0-9]{4}-4[A-F0-9]{3}-[89AB][A-F0-9]{3}-[A-F0-9]{12}

Проверить с помощью

uuidgen | grep -E "[A-F0-9]{8}-[A-F0-9]{4}-4[A-F0-9]{3}-[89AB][A-F0-9]{3}-[A-F0-9]{12}"

Вариант для C++:

#include <regex>  // Required include

...

// Source string    
std::wstring srcStr = L"String with GIUD: {4d36e96e-e325-11ce-bfc1-08002be10318} any text";

// Regex and match
std::wsmatch match;
std::wregex rx(L"(\\{[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}\\})", std::regex_constants::icase);

// Search
std::regex_search(srcStr, match, rx);

// Result
std::wstring strGUID       = match[1];

Для bash:

grep -E "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}"

Например:

$> echo "f2575e6a-9bce-49e7-ae7c-bff6b555bda4" | grep -E "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}"
f2575e6a-9bce-49e7-ae7c-bff6b555bda4
$UUID_RE = join '-', map { "[0-9a-f]{$_}" } 8, 4, 4, 4, 12;

Кстати, разрешение только 4 на одну из позиций действительно только для UUIDv4. Но v4 не единственная версия UUID, которая существует. Я встречал v1 и в моей практике.

Я просто хочу поделиться наименьшим способом регулярного выражения, чтобы сделать то же самое из хороших ответов здесь.

[a-f\d]{8}(-[a-f\d]{4}){3}-[a-f\d]{12}$

Пожалуйста, используйте с флагом игнорирования регистраiдля игнорирования регистра/без учета регистра:

      const pattern = /^[a-f\d]{8}(-[a-f\d]{4}){3}-[a-f\d]{12}$/i // JavaScript
      pattern = re.compile(r"^[a-f\d]{8}(-[a-f\d]{4}){3}-[a-f\d]{12}$", re.IGNORECASE) # Python
      $pattern = '/^[a-f\d]{8}(-[a-f\d]{4}){3}-[a-f\d]{12}$/i' // php

Хотел внести свой вклад, так как мое регулярное выражение охватывает все случаи из OP и правильно группирует все соответствующие данные по методу группы (вам не нужно отправлять строку обработки, чтобы получить каждую часть uuid, это регулярное выражение уже получило это для вас )

      ([\d\w]{8})-?([\d\w]{4})-?([\d\w]{4})-?([\d\w]{4})-?([\d\w]{12})|[{0x]*([\d\w]{8})[0x, ]{4}([\d\w]{4})[0x, ]{4}([\d\w]{4})[0x, {]{5}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})[0x, ]{4}([\d\w]{2})

Обобщите один, где подчеркивание также игнорируется должным образом и разрешены только буквенно-цифровые значения с шаблоном 8-4-4-4-12.

^[^\W_]{8}(-[^\W_]{4}){4}[^\W_]{8}$

или

^[^\W_]{8}(-[^\W_]{4}){3}-[^\W_]{12}$

оба дают одинаковый результат, но последний более читаем. И я хотел бы порекомендовать сайт, где можно научиться, а также правильно протестировать регулярное выражение: https://regexr.com/

Официальная библиотека uuid использует следующее регулярное выражение:

      /^(?:[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

См. ссылку

Другие вопросы по тегам