Как вычисляется регулярное выражение ИЛИ оператор

#python #regex

#c# #.net #sql-сервер #регулярное выражение #sql-server-2012

Вопрос:

В T-SQL я сгенерировал уникальный идентификатор с помощью функции NEWID(). Например:

 723952A7-96C6-421F-961F-80E66A4F29D2
  

Затем все тире ( - ) удаляются, и это выглядит следующим образом:

 723952A796C6421F961F80E66A4F29D2
  

Теперь мне нужно преобразовать приведенную выше строку в допустимую, UNIQUEIDENTIFIER используя следующий формат xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx и снова установив тире.

Для достижения этой цели я использую SQL CLR реализацию C# RegexMatches функции с этим ^.{8}|.{12}$|.{4} регулярным выражением, которое дает мне это:

 SELECT *
FROM [dbo].[RegexMatches] ('723952A796C6421F961F80E66A4F29D2', '^.{8}|.{12}$|.{4}')
  

введите описание изображения здесь

Используя вышесказанное, я могу легко создать правильное, UNIQUEIDENTIFIER но мне интересно, как OR оператор вычисляется в регулярном выражении. Например, следующее не будет работать:

 SELECT *
FROM [dbo].[RegexMatches] ('723952A796C6421F961F80E66A4F29D2', '^.{8}|.{4}|.{12}$')
  

введите описание изображения здесь

Уверен ли он, что первое регулярное выражение сначала будет соответствовать началу и концу строки, затем другим значениям и всегда возвращает совпадения в этом порядке (у меня будут проблемы, если, например, 96C6 будет сопоставлено после 421F ).

Комментарии:

1. Кроме того, причина, по которой ^.{8}|.{4}|.{12}$ возвращаются блоки по четыре вместо последнего из 12, связана с тем фактом, что используется первое or (|) значение, которое совпадает, не самое точное. Анализатор регулярных выражений видит .{4} прежде, чем он увидит .{12}$ , и поэтому сопоставляет их в квадратах.

2. @EBrown, эта ситуация является частью сложного приложения. Я не могу изменить способ, которым это делается. Просто нужно найти способ справиться с этой ситуацией.

3. @EBrown, значит, он всегда соответствует OR блоку в порядке?

4. Почему вы используете регулярное выражение, чтобы разделить это? Вы точно знаете, где тире должны быть вставлены повторно. Например. STUFF(STUFF(STUFF(STUFF(UnDashedValue,21,0,'-'),17,0,'-'),13,0,'-'),9,0,'-') выполняет работу.

5. Мы должны работать с разными определениями clear . Т. е. тот факт, что вам приходится задавать вопрос о варианте регулярного выражения, мне кажется, что это может быть не «ясно».

Ответ №1:

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

Взяв в качестве примера шаблон, который у вас есть, ^.{8}|.{12}$|.{4} начинает проверку входной строки слева и проверяет наличие ^.{8} первых 8 символов. Находит их, и это совпадение. Затем идет дальше и находит последние 12 символов с .{12}$ , и снова есть совпадение. Затем сопоставляются любые 4-символьные строки.

Визуализация регулярного выражения

Демонстрация Debuggex

Далее у вас есть ^.{8}|.{4}|.{12}$ . Выражение снова анализируется слева направо, сначала сопоставляются первые 8 символов, но затем будут сопоставлены только последовательности из 4 символов, .{12} которые никогда не сработают, потому что будут .{4} совпадения!

Визуализация регулярного выражения

Демонстрация Debuggex

Ответ №2:

Ваше регулярное выражение ^.{8}|.{12}$|.{4} вычисляется как:

Начиная с любого символа, кроме n { Ровно 8 раз}

ИЛИ любой символ, кроме n { Ровно 12 раз}

ИЛИ любой символ, кроме n {Ровно 4 раза} глобально

Это означает, что все, что находится после 4 символов в строке, будет сопоставлено, потому что где-то в строке из > 4 символов есть 4 символа в строке.

1 [false]

12 [false]

123 [false]

1234 [верно]

12345 [верно]

123456 [верно]

1234567 [верно]

12345678 [верно]

123456789 [верно]

1234567890 [верно]

12345678901 [верно]

123456789012 [верно]

Возможно, вы ищете:

^.{8}$|^.{12}$|^.{4}$

Что дает вам:

1 [false]

12 [false]

123 [false]

1234 [верно]

12345 [false]

123456 [false]

1234567 [false]

12345678 [верно]

123456789 [false]

1234567890 [false]

12345678901 [false]

123456789012 [верно]