#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 — Получение результата с помощью функции ЗАМЕНЫ