С# Simple Regex - 32 символа, содержащие только 0-9 и a-f (GUID)

Как проверить использование регулярного выражения в С#, если:

  • длина строки равна 32 Строка
  • содержит только числа от 0 до 9 и маленькие буквы от a-f

Ответы

Ответ 1

Как насчет:

Regex regex = new Regex("^[0-9a-f]{32}$");
if (regex.IsMatch(text))
...

Ответ 3

Если вы не настроены на использование Regex для этой цели, это довольно чисто:

Func<char, bool> charValid = c => (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
bool isValid = text.Length == 32 && text.All(charValid);

Ответ 4

Итак, здесь есть ответ, который показывает вам, как узнать, имеет ли эта строка 32 символа в длину, и каждый символ представляет собой либо цифру, либо нижний регистр "a" в нижний регистр "f" с регулярным выражением, а другой, который показывает вам, как это сделать с помощью простого Func, который сканирует эти символы в строке. Они оба отличные ответы и технически правильные, но в заголовке вопроса вы явно указываете "GUID", который открывает новую банку червей.

GUID могут принимать несколько различных строковых представлений, и вы можете столкнуться с любым из них. Вам нужно справиться с этим? Вам нужно будет разместить строки, которые начинаются и заканчиваются фигурными фигурными скобками ('{' и '}') или круглыми скобками? Как насчет тире ('-')? В соответствии с MSDN, создавая новый GUID с

string s = ...;
Guid g = new Guid(s);

Позволяет использовать строки в следующих формах

32 смежных цифры: ddddddddddddddddddddddddddddddd

-or-

Группы из 8, 4, 4, 4 и 12 цифр с дефисами между группами. весь GUID может быть дополнительно включен в соответствующих скобках или круглых скобках: dddddddd-dddd-dddd-dddd-dddddddddddd

-or-

{DDDDDDDDDDDD-DDDDDDDD-DDDDDDDDDDDD}

-or-

(DDDDDDDDDDDD-DDDDDDDD-DDDDDDDDDDDD)

-or-

Группы из 8, 4 и 4 цифр и подмножество из восьми групп из 2 цифр, с каждой группой с префиксом "0x" или "0X" и разделены запятыми. весь GUID, а также подмножество, заключенные в соответствующие фигурные скобки: {0xdddddddd, 0xdddd, 0xdddd, {0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd}}

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

Я быстро проверил тест производительности на трех разных способах определения, является ли строка фактически строковым представлением GUID:

  • Regex
  • Проверка всех символов в строке
  • Создание нового экземпляра Guid с данной строкой (если Guid может быть создан, то строка является допустимым строковым представлением)

Здесь код:

[Тест]

public void Test_IsRegex_Performance()
{
    Action withRegexMatch = () =>
    {
        Regex regex = new Regex("^[0-9a-f]{32}$");
        Guid g = new Guid();
        string s = g.ToString();
        regex.IsMatch(s);
    };

    Action withCharCheck = () =>
    {
        Guid g = new Guid();
        string s = g.ToString();

        Func<char, bool> charValid = c => (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
        bool isValid = s.Length == 32 && s.All(charValid);
    };

    Action withNewGuid = () =>
    {
        Guid g = new Guid();
        string s = g.ToString();
        try
        {
            Guid g2 = new Guid(s);
            // if no exception is thrown, this is a valid string 
            // representation
        }
        catch
        {
            // if an exception was thrown, this is an invalid
            // string representation
        }
    };

    const int times = 100000;

    Console.WriteLine("Regex: {0}", TimedTask(withRegexMatch, times));
    Console.WriteLine("Checking chars: {0}", TimedTask(withCharCheck, times));
    Console.WriteLine("New Guid: {0}", TimedTask(withNewGuid, times));
    Assert.Fail();
}

private static TimeSpan TimedTask(Action action, int times)
{
    Stopwatch timer = new Stopwatch();
    timer.Start();
    for (int i = 0; i < times; i++)
    {
        action();
    }
    timer.Stop();
    return timer.Elapsed;
}

И результаты миллиона итераций на моей машине:

Regex: 00:00:10.1786901
Checking chars: 00:00:00.2504520
New Guid: 00:00:01.3129005

Итак, решение регулярного выражения медленное. Спросите себя, действительно ли вам нужно регулярное выражение. Обратите внимание, что вы можете, возможно, извлечь дополнительную производительность, только объявив регулярное выражение один раз и повторно используя его, но я думаю, что в этом случае вам может быть лучше, если посмотреть на то, что вы пытаетесь выполнить, в отличие от как.

Надеюсь, что это поможет.