如何定义具有多个OR运算符的正则表达式,其中每个项都包含一个空格前缀和后缀



我正在为数据提取任务做准备。我需要删除一组术语;在每个源记录字符串中可能不存在、部分或全部。目标记录超过100000条。我希望避免执行单术语匹配/替换操作,因为(a)要删除的术语列表可能会增加,以及(b)每次执行一个术语的当前匹配/替换动作的时间是不可接受的。

我的问题是:如何修改正则表达式以将每个项都包含在OR分隔的列表中?

正则表达式

' and | and or | a o | company | co | c o | dba | d b a '

期望行为

将找到的每个术语(包括前缀和后缀空间)替换为一个空格。

实际行为

找到的每个"偶数"(与"奇数"相反)术语都用一个空格替换(包括前缀和后缀空间)。

示例

源字符串

'   MASHABLE LTD DBA THE INFORMATION EXPERTS and and or a o company co c o dba d b a COPYRIGHT  '

结果字符串(期望行为)

'   MASHABLE LTD THE INFORMATION EXPERTS COPYRIGHT  '

结果字符串(实际行为)

'   MASHABLE LTD THE INFORMATION EXPERTS and or company c o d b a COPYRIGHT  '

环境

SQL Server 2005

用户定义函数regexReplace依赖VBScript.RegExp(文章末尾提供的代码)

代码

set nocount on
declare @source [varchar](800)
declare @regexp [varchar](400)
declare @replace [char](1)
declare @globalReplace [bit]
declare @ignoreCase [bit]
declare @result [varchar](800)
set @globalReplace = 1
set @ignoreCase = 1
SET @source = '   MASHABLE LTD DBA THE INFORMATION EXPERTS and and or a o company co c o dba d b a COPYRIGHT  '
set @regexp = ' and | and or | a o | company | co | c o | dba | d b a '
set @replace = ' '
select @result = master.dbo.regexReplace(@source,@regexp,@replace,@globalReplace,@ignoreCase)
print @result

产生结果:

   MASHABLE LTD THE INFORMATION EXPERTS and or company c o d b a COPYRIGHT  

*dbo.regex替换用户定义的函数定义*

CREATE FUNCTION [dbo].[regexReplace]
    (
    @source varchar(5000),
    @regexp varchar(1000),
    @replace varchar(1000),
    @globalReplace bit = 0,
    @ignoreCase bit = 0
    )
    RETURNS varchar(1000) AS
        BEGIN
            DECLARE @hr integer
            DECLARE @objRegExp integer
            DECLARE @result varchar(5000)
            EXECUTE @hr = sp_OACreate 'VBScript.RegExp', @objRegExp OUTPUT
            IF @hr <> 0 
                BEGIN
                    EXEC @hr = sp_OADestroy @objRegExp
                    RETURN NULL
                END
            EXECUTE @hr = sp_OASetProperty @objRegExp, 'Pattern', @regexp
            IF @hr <> 0 
                BEGIN
                    EXEC @hr = sp_OADestroy @objRegExp
                    RETURN NULL
                END
            EXECUTE @hr = sp_OASetProperty @objRegExp, 'Global', @globalReplace
            IF @hr <> 0 
                BEGIN
                    EXEC @hr = sp_OADestroy @objRegExp
                    RETURN NULL
                END
            EXECUTE @hr = sp_OASetProperty @objRegExp, 'IgnoreCase', @ignoreCase
            IF @hr <> 0 
                BEGIN
                    EXEC @hr = sp_OADestroy @objRegExp
                    RETURN NULL
                END
            EXECUTE @hr = sp_OAMethod @objRegExp, 'Replace', @result OUTPUT, @source, @replace
            IF @hr <> 0 
                BEGIN
                    EXEC @hr = sp_OADestroy @objRegExp
                    RETURN NULL
                END
            EXECUTE @hr = sp_OADestroy @objRegExp
                IF @hr <> 0 
                    BEGIN
                        RETURN NULL
                    END
            RETURN @result
        END

试试这个:

(?: (?:and or|and|a o|company|co|c o|dba|d b a))+(?!S)/i

像@mathematical.coffee一样,我一开始就分解了前导空格,并用前瞻性替换了尾随空格——在这种情况下,对于非空白字符,使用前瞻性。这样,即使令牌是字符串中的最后一个,并且后面没有空格,它也能工作。但最重要的变化是尽可能一次更换两场或两场以上的比赛。

这不是SQL Server的问题。这是一个常见的RegEx问题,而不仅仅是通过COM访问的VBScript引擎中包含的问题。问题是新旧前缀空间之间的匹配实际上重叠。

我在中试过你的例子http://www.regextester.com/它也做同样的事情。

第一个未被替换的"and or"实际上是由第一个和"之间的空格组成的,该空格被空格替换,然后是剩余的文本。

我会考虑使用单词边界替换:Regex匹配并替换由特定字符

分隔的单词

我推荐这个正则表达式:

( (and(?: or)?|a o|company|c ?o|d ?b ?a)(?= ))

首先,我把前缀/后缀空格放在OR括号外(效率):

( (and(?: or)?|a o|company|c ?o|d ?b ?a) )

但是,当您使用此正则表达式时,匹配项会重叠。例如,and and or首先与and匹配,但随后剩下的字符串是没有前面空间的and or

因此,为了避开这一点,我将最后一个空格改为正面展望。上面写着"确保这个模式后面有一个空格",但与空格本身不匹配。

因此,当经过and and or时,它与and匹配,并离开and or,这也与模式匹配。它或多或少地消除了重叠匹配的问题。如果某个单词出现在字符串的末尾,则它将与您的某个单词不匹配,但您的原始regex无论如何都不匹配。

您可以在regexr站点上看到它的实际操作。注意,如果你用一个空格替换每个匹配项,你会得到太多的空格:

MASHABLE LTD  THE INFORMATION EXPERTS         COPYRIGHT

但无论如何,您的原始regex都会有这个问题。如果你完全删除匹配,你会得到:

MASHABLE LTD THE INFORMATION EXPERTS COPYRIGHT

最新更新