删除字符左侧和右侧的单词

remove word to left and right of character

使用 MS SQL 2008,我需要删除文本字符串中包含的电子邮件地址。即:

“这是一个包含多个电子邮件地址的示例文本行,例如 fred@example.com 或者我也可以让 bert@home.co.uk 甚至 someone@somewhere.pl 来混合使用".

期望的结果是:

“这是包含多个电子邮件地址的示例文本行,或者我也可以拥有甚至混合使用”

甚至:

“这是一个包含多个电子邮件地址的示例文本行,例如 fred@***** 或者我也可以让 bert@***** 甚至 someone@***** 来混淆".

有很多删除特定字符左侧或右侧所有内容的示例,但不是删除第一个 space 之前固定字符左侧或右侧的文本。感谢您的帮助。

假设文本字符串在 table 列中,您可以在 SQL Server 2008 中借助字符串复制功能和通过 for xml 进行的字符串连接来完成此操作。在较新版本的 SQL 服务器中——你真的应该尝试迁移到它——使用 string_agg 之类的函数而不是 stuff( ... for xml ) 组合可以使这变得更容易。

这个实现是贪婪的,因为它会屏蔽两个空格(或字符串的 start/end)之间至少包含一个 @ 字符的任何字符组合。所以 fullsentences-like^this'one%will£be$included,so\long)as/there>is.a=@*character&somewhere 以及仅由一个或多个 @ 字符组成的字符串。

我将如何处理 不是 电子邮件地址的字符串留给您。

查询

with t as
(
    select *
    from(values('This is a sample line of text with multiple email addresses like fred@example.com or I could also have bert@home.co.uk or even someone@somewhere.pl to mix things up')
              ,('This is another sample line of text with multiple email addresses like fred2@example2.com or I could also have bert2@home2.co.uk or even someone2@somewhere2.pl to mix things up')
              ,('fullsentences-like^this''one%will£be$included,so\long)as/there>is.a=@*character&somewhere')
              ,('@')
              ,('a @@@@@ b')
              ,('@ @ @ @ @')
              ,('Let''s meet @ the beach')
        ) as s(s)
)
,s as
(
    select t.s
          ,s.rn
          ,case when charindex('@',s.item) > 0 then '***' else s.item end as item
    from t
        cross apply dbo.fn_StringSplit4k(t.s,' ',null) as s
)
select t.s
      ,stuff((select ' ' + s.item
              from s
              where t.s = s.s
              order by s.rn
              for xml path('')
             )
            ,1,1,''
            ) as s
from t;

输出

s s
This is a sample line of text with multiple email addresses like fred@example.com or I could also have bert@home.co.uk or even someone@somewhere.pl to mix things up This is a sample line of text with multiple email addresses like *** or I could also have *** or even *** to mix things up
This is another sample line of text with multiple email addresses like fred2@example2.com or I could also have bert2@home2.co.uk or even someone2@somewhere2.pl to mix things up This is another sample line of text with multiple email addresses like *** or I could also have *** or even *** to mix things up
fullsentences-like^this'one%will£be$included,so\long)as/there>is.a=@*character&somewhere ***
@ ***
a @@@@@ b a *** b
@ @ @ @ @ *** *** *** *** ***
Let's meet @ the beach Let's meet *** the beach

字符串拆分函数

create function [dbo].[fn_StringSplit4k]
(
     @str nvarchar(4000) = ' '              -- String to split.
    ,@delimiter as nvarchar(1) = ','        -- Delimiting value to split on.
    ,@num as int = null                     -- Which value to return.
)
returns table
as
return
                    -- Start tally table with 10 rows.
    with n(n)   as (select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1)

                    -- Select the same number of rows as characters in @str as incremental row numbers.
                    -- Cross joins increase exponentially to a max possible 10,000 rows to cover largest @str length.
        ,t(t)   as (select top (select len(isnull(@str,'')) a) row_number() over (order by (select null)) from n n1,n n2,n n3,n n4)

                    -- Return the position of every value that follows the specified delimiter.
        ,s(s)   as (select 1 union all select t+1 from t where substring(isnull(@str,''),t,1) = @delimiter)

                    -- Return the start and length of every value, to use in the SUBSTRING function.
                    -- ISNULL/NULLIF combo handles the last value where there is no delimiter at the end of the string.
        ,l(s,l) as (select s,isnull(nullif(charindex(@delimiter,isnull(@str,''),s),0)-s,4000) from s)
    
    select rn
          ,item
    from(select row_number() over(order by s) as rn
               ,substring(@str,s,l) as item
        from l
        ) a
    where rn = @num
       or @num is null;