Регулярное выражение в функции замены SQL Server

#sql-server #string-matching

Вопрос:

У меня есть переменная со случайным текстом, скажем

 DECLARE @sNumberFormat NVARCHAR(200) = 'rand{text.here,{999}also-Random9He8re'  

Я хочу заменить каждый 9 из них на {999} [0-9] . Поэтому в этом примере я хотел бы получить

 'rand{text.here,[0-9][0-9][0-9]also-Random9He8re'  

Проблема в том, что я никогда не знаю, сколько 9 будет помещено в скобки, так что может быть {99} {9999} … и продолжайте. Мне также нужно проверить, есть ли какой-либо недопустимый символ (нет 9 ), тогда ничего не следует заменять.

Я пробовал некоторые комбинации REPLACE функций и PATINDEX функций, но мне это не удалось.

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

1. SQL Server не поддерживает регулярные выражения, и его возможности сопоставления шаблонов в лучшем случае являются рудиментарными.

Ответ №1:

Без надежной поддержки регулярных выражений собственные функции SQL Server здесь не оказывают большой помощи. Один из подходов, немного банальный, состоял бы в том, чтобы разделить входную строку на три компонента:

 rand{text.here, {999} also-Random9He8re  

Затем замените 9 целевую подстроку в середине @ на или какой-либо другой символ, который , как вы ожидаете, больше нигде не появится в вашей входной строке:

 rand{text.here, {@@@} also-Random9He8re  

Наконец, замените @ подстроку в середине [0-9] на, а затем объедините вместе, чтобы получить конечный результат:

 DECLARE @val NVARCHAR(200) = 'rand{text.here,{999}also-Random9He8re'  SELECT REPLACE(  SUBSTRING(@val, 1, CHARINDEX('{9', @val) - 1)    REPLACE(SUBSTRING(@val,  CHARINDEX('{9', @val)   1,  CHARINDEX('9}', @val) - CHARINDEX('{9', @val)), '9', '@')    SUBSTRING(@val, CHARINDEX('9}', @val)   2, LEN(@val) - CHARINDEX('9}', @val)),  '@', '[0-9]');  

Ответ №2:

Итак, ленивый дев во мне предлагает это:

 SELECT Replace(  Replace(  Replace(  Replace(@input, '{9999}', '[0-9][0-9][0-9][0-9]')  , '{999}', '[0-9][0-9][0-9]')  , '{99}', '[0-9][0-9]')  , '{9}', '[0-9]') AS result ;  

Вы можете продолжать продлевать до тех пор, пока вам нравится выполнять свои (одноразовые?) замены.

Быстрый. Простой. Расширяемый. Хаки.

Иногда лени бывает достаточно.

Ответ №3:

Это можно было бы сделать с помощью серии CTE. Он работает с произвольным числом значений «9» в квадратных скобках.

 Declare @str varchar(max) = 'rand{text.here,{999}also-Random9He8re';  With A As  (Select 1 As Pos Union All  Select Pos 1 As Pos From A Where Pos lt; LEN(@str) ), B As ( Select STRING_AGG(Case When Chr Like '[{9}]' Then Chr Else ' ' End, '') As Chr  From A Cross Apply (Select SUBSTRING(@str,A.Pos,1 )) As T(chr) ), C As ( Select [value] As pattern,   REPLACE(REPLACE(REPLACE([value], '9', '[0-9]'),'{',''),'}','') As replacement,   ROW_NUMBER() Over (ORDER BY (SELECT NULL)) As Num,   COUNT(*) OVER (ORDER BY (SELECT NULL)) As Cnt From B Cross Apply STRING_SPLIT(Chr,' ') Where [value] Like '{%}' And [value] Like '%9%' ), D As ( Select @str As Result, 1 As Num Union All  select REPLACE(Result, C.pattern, C.replacement) As Res , D.Num 1 As Num From D Inner Join C On (D.Num=C.Num) Where D.Numlt;=C.Cnt) Select Top 1 Result From D Order by Num Desc  
  • A — Получение списка позиций символов в тексте
  • B — Получение текста с пробелами вместо символов, отличных от ‘9’,'{‘,’}’
  • C — Получение шаблонов и соответствующих значений замены
  • D — Получение результата с помощью функции ЗАМЕНЫ