【问题标题】:Regex in SQL Server Replace functionSQL Server 替换函数中的正则表达式
【发布时间】:2021-12-27 09:59:54
【问题描述】:

假设我有一个带有随机文本的变量

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

我想用[0-9] 替换{999} 中的每个9。所以在这个例子中我想得到

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

问题是我永远不知道有多少个9 会放在括号中,所以可以有{99} {9999} ..然后继续。我还需要验证是否有任何无效字符(不是9),那么什么都不应该被替换。

我尝试了REPLACEPATINDEX 函数的一些组合,但我无法实现。

【问题讨论】:

  • SQL Server 不支持正则表达式,它的模式匹配能力充其量是初级的。

标签: sql-server string-matching


【解决方案1】:

没有强大的正则表达式支持,SQL Server 的本机函数在这里没有提供太多帮助。一种有点hackish的方法是将输入字符串分成三个部分:

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
    ;
    

    您可以继续扩展,只要您愿意执行(一次性?)替换。

    快。简单的。可扩展。 Hacky

    有时懒惰是足够好的

    【讨论】:

      【解决方案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 < 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.Num<=C.Cnt)
      Select Top 1 Result
      From D
      Order by Num Desc
      
      • A - 获取文本中的字符位置列表
      • B - 获取带有空格的文本,而不是其他字符 '9','{','}'
      • C- 获取模式和对应的替换值
      • D - 使用 REPLACEMENT 函数获取结果

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-26
        • 1970-01-01
        • 1970-01-01
        • 2017-10-07
        • 2014-06-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多