zoukankan      html  css  js  c++  java
  • SQL SERVER 正则替换

    原文链接:http://blog.csdn.net/maco_wang/article/details/7390212


    RegExp对象提供简单的正则表达式支持功能:

    1.Global属性设置或返回一个 Boolean 值,该值指明在整个搜索字符串时模式是全部匹配还是只匹配第一个。
      语法:
       object.Global [= True | False ]
       object 参数总是 RegExp 对象。如果搜索应用于整个字符串,Global 属性的值为 True,否则其值为 False。默认的设置为 True。


    2.IgnoreCase属性设置或返回一个Boolean值,指明模式搜索是否区分大小写。
      语法:
    object.IgnoreCase [= True | False ]
          object 参数总是一个 RegExp 对象。如果搜索是区分大小写的,则 IgnoreCase 属性为 False;否则为 True。缺省值为 True。


    3.Pattern属性设置或返回被搜索的正则表达式模式。 
      语法:
            object.Pattern [= "searchstring"]

    4.Pattern 属性的语法包含以下几个部分:

    设置
      在书写正则表达式的模式时使用了特殊的字符和序列。下面描述了可以使用的字符和序列,并给出了实例。
     \ 将下一个字符标记为特殊字符或字面值。例如"n"与字符"n"匹配。"\n"与换行符匹配。序列"\\"与"\"匹配对面,"\("与"("匹配。 
     ^ 匹配输入的开始位置。 
     $ 匹配输入的结尾。 
     * 匹配前一个字符零次或几次。例如,"zo*"可以匹配"z"、"zoo"。 
     + 匹配前一个字符一次或多次。例如,"zo+"可以匹配"zoo",但不匹配"z"。 
     ? 匹配前一个字符零次或一次。例如,"a?ve?"可以匹配"never"中的"ve"。 
     . 匹配换行符以外的任何字符。 
     (pattern) 与模式匹配并记住匹配。匹配的子字符串可以从作为结果的 Matches 集合中使用 Item [0]...[n]取得。如果要匹配括号字符(和 ),可使用"\(" 或 "\)"。 
     x|y 匹配 x 或 y。例如 "z|food" 可匹配 "z" 或 "food"。"(z|f)ood" 匹配 "zoo" 或 "food"。 
     {n} n 为非负的整数。匹配恰好n次。例如,"o{2}" 不能与 "Bob 中的 "o" 匹配,但是可以与"foooood"中的前两个o匹配。 
     {n,} n 为非负的整数。匹配至少n次。例如,"o{2,}"不匹配"Bob"中的"o",但是匹配"foooood"中所有的o。"o{1,}"等价于"o+"。"o{0,}"等价于"o*"。 
     {n,m} m 和 n 为非负的整数。匹配至少 n 次,至多 m 次。例如,"o{1,3}" 匹配 "fooooood"中前三个o。"o{0,1}"等价于"o?"。 
     [xyz] 一个字符集。与括号中字符的其中之一匹配。例如,"[abc]" 匹配"plain"中的"a"。 
     [^xyz] 一个否定的字符集。匹配不在此括号中的任何字符。例如,"[^abc]" 可以匹配"plain"中的"p". 
     [a-z] 表示某个范围内的字符。与指定区间内的任何字符匹配。例如,"[a-z]"匹配"a"与"z"之间的任何一个小写字母字符。 
     [^m-z] 否定的字符区间。与不在指定区间内的字符匹配。例如,"[m-z]"与不在"m"到"z"之间的任何字符匹配。 
     \b 与单词的边界匹配,即单词与空格之间的位置。例如,"er\b" 与"never"中的"er"匹配,但是不匹配"verb"中的"er"。 
     \B 与非单词边界匹配。"ea*r\B"与"never early"中的"ear"匹配。 
     \d 与一个数字字符匹配。等价于[0-9]。 
     \D 与非数字的字符匹配。等价于[^0-9]。 
     \f 与分页符匹配。 
     \n 与换行符字符匹配。 
     \r 与回车字符匹配。 
     \s 与任何白字符匹配,包括空格、制表符、分页符等。等价于"[ \f\n\r\t\v]"。 
     \S 与任何非空白的字符匹配。等价于"[^ \f\n\r\t\v]"。 
     \t 与制表符匹配。 
     \v 与垂直制表符匹配。 
     \w 与任何单词字符匹配,包括下划线。等价于"[A-Za-z0-9_]"。 
     \W 与任何非单词字符匹配。等价于"[^A-Za-z0-9_]"。 
     \num 匹配 num个,其中 num 为一个正整数。引用回到记住的匹配。例如,"(.)\1"匹配两个连续的相同的字符。 
     \n 匹配 n,其中n 是一个八进制换码值。八进制换码值必须是 1, 2 或 3 个数字长。例如,"\11" 和 "\011" 都与一个制表符匹配。"\0011"等价于"\001" 与 "1"。八进制换码值不得超过 256。否则,只有前两个字符被视为表达式的一部分。允许在正则表达式中使用ASCII码。 
     \xn 匹配n,其中n是一个十六进制的换码值。十六进制换码值必须恰好为两个数字长。例如,"\x41"匹配"A"。"\x041"等价于"\x04" 和 "1"。允许在正则表达式中使用 ASCII 码。


    --====================================
    --标题: 应用实例之SQL SERVER 正则替换
    --作者:maco_wang
    --时间:2012-03-24
    --说明:MS-SQL SERVER 中的正则替换
    --补充说明:支持一下CSDN社区支持的活动
    --====================================
    
    /*
    假设测试数据为:
    col
    ----------------------
    192abc168xx0yya101baaa
    10hh176bag98job121zero
    hello112u19aa110beyp45
    a80abab230pppp120qu224
    121nile21reply30vall90
    
    想要得到的结果(把字段中的连续的字母替换成'.'):
    col
    --------------
    192.168.0.101
    10.176.98.121
    112.19.110.45
    80.230.120.224
    121.21.30.90
    */
    
    --测试数据:
    if object_id('[tb]') is not null drop table [tb]
    create table [tb] (col varchar(100))
    insert into [tb]
    select '192abc168xx0yya101baaa' union all
    select '10hh176bag98job121zero' union all
    select 'hello112u19aa110beyp45' union all
    select 'a80abab230pppp120qu224' union all
    select '121nile21reply30vall90'
    
    --本示例在SQL SERVER 2005版本即可适用。
    
    --正常思路
    --a)游标循环截取(略)
    --b)自定义函数
    go
    create function [dbo].[fn_replace]
    (
        @str nvarchar(100)
    )
    returns varchar(100)
    as
    begin
        while patindex('%[a-z]%',@str) > 0
        begin
            set @str = stuff(@str,patindex('%[a-z]%',@str),1,N'.');
        end
        while (charindex('..',@str)<>0)
        begin
            set @str=replace(@str,'..','.')
        end
        if(left(@str,1)='.') set @str=right(@str,len(@str)-1)
        if(right(@str,1)='.') set @str=left(@str,len(@str)-1)
        return @str
    end
    go
    select dbo.[fn_replace](col) as col from [tb]
    /*
    col
    ---------------
    192.168.0.101
    10.176.98.121
    112.19.110.45
    80.230.120.224
    121.21.30.90
    */
    --c)其他方法,这里我主要介绍一下正则替换,因为patindex和like 能够支持的正则还是非常少的
    
    --正则替换
    --开启xp_cmdshell
    --不开启会提示:SQL Server blocked access to procedure 'xp_cmdshell'
    go
    sp_configure 'show advanced options', 1
    go
    reconfigure
    go
    sp_configure 'xp_cmdshell', 1
    go
    reconfigure
    
    
    --开启sp_OACreate
    --不开启会提示:SQL Server blocked access to procedure 'sys.sp_OACreate'
    go
    sp_configure 'show advanced options', 1;
    go
    reconfigure;
    go
    sp_configure 'ole automation procedures', 1;
    go
    reconfigure;
    go
    
    --创建函数
    create function [dbo].[regexReplace]
    (
        @source varchar(8000),    --字符串
        @regexp varchar(500),     --正则表换式
        @replace varchar(500),    --替换值
        @globalReplace bit = 0,   --是否是全局替换
        @ignoreCase bit = 0       --是否忽略大小写
    )
    returns varchar(1000) AS
    begin
        declare @hr int
        declare @objRegExp int
        declare @result varchar(5000)
    
        exec @hr = sp_OACreate 'VBScript.RegExp', @objRegExp output
        if @hr <> 0 
        begin
            exec @hr = sp_OADestroy @objRegExp
            return null
        end
        exec @hr = sp_OASetProperty @objRegExp, 'Pattern', @regexp
        if @hr <> 0 
        begin
            exec @hr = sp_OADestroy @objRegExp
            return null
        end
        exec @hr = sp_OASetProperty @objRegExp, 'Global', @globalReplace
        if @hr <> 0 
        begin
            exec @hr = sp_OADestroy @objRegExp
            return null
        end
        exec @hr = sp_OASetProperty @objRegExp, 'IgnoreCase', @ignoreCase
        if @hr <> 0 
        begin
            exec @hr = sp_OADestroy @objRegExp
            return null
        end 
        exec @hr = sp_OAMethod @objRegExp, 'Replace', @result output, @source, @replace
        if @hr <> 0 
        begin
            exec @hr = sp_OADestroy @objRegExp
            return null
        end
        exec @hr = sp_OADestroy @objRegExp
        if @hr <> 0 
        begin
            return null
        end
    /* 注释A
    --    while (charindex('..',@result)<>0)
    --    begin
    --        set @result=replace(@result,'..','.')
    --    end
    --    if(left(@result,1)='.')
    --        set @result=right(@result,len(@result)-1)
    --    if(right(@result,1)='.')
    --        set @result=left(@result,len(@result)-1)
    */
        return @result
    end
    
    --查看结果
    go
    select dbo.regexReplace(col,'[a-z]','.',1,0) as col from [tb]
    /*
    col
    -----------------------
    192...168..0...101....
    10..176...98...121....
    .....112.19..110....45
    .80....230....120..224
    121....21.....30....90
    */
    
    --根据正则把字母替换成'.'后的结果和想要结果并不相同
    --需要把函数中的"注释A"取消注释,才能保证结果相同,那就不如直接用上述自定义函数
    --那么有没有其他办法呢?
    
    --tb表中的字符长度为100,那么修改正则表达式,把连续的替换成'.'试一试
    --匹配的模式是包含a-z的任何字母,匹配次数可以是1-100次,把字母替换成'.',不区分大小写
    select dbo.regexReplace(col,'[a-z]{1,100}','.',1,0) as col from [tb]
    /*
    col
    ------------------
    192.168.0.101.
    10.176.98.121.
    .112.19.110.45
    .80.230.120.224
    121.21.30.90
    */
    
    --结果还是不相同
    --开头结尾还是有多余的'.'
    --不想用left,right,substring截取,修改正则能不能搞定呢?
    
    --再修改一下
    --内部的:匹配的模式是包含a-z的任何字母,匹配次数可以是1-100次,把字母替换成'.',不区分大小写
    --外部的:匹配开头是一个'.'或者结尾是一个'.'的,替换成空格。
    select 
    col=dbo.regexReplace(dbo.regexReplace(col,'[a-z]{1,100}','.',1,0),'^\.{1}|\.{1}$','',1,0)
    from [tb]
    
    /*
    col
    ----------------
    192.168.0.101
    10.176.98.121
    112.19.110.45
    80.230.120.224
    121.21.30.90
    */
    
    --这个例子对正则的应用还是比较简单的,我这里只是介绍一个思路。
    


  • 相关阅读:
    caffe常用层: batchNorm层和scale层
    简述configure、pkg-config、pkg_config_path三者的关系
    python删除list中元素的三种方法
    Leetcode 872. Leaf-Similar Trees
    Leetcode 508. Most Frequent Subtree Sum
    Leetcode 572. Subtree of Another Tree
    Leetcode 894. All Possible Full Binary Trees
    Leetcode 814. Binary Tree Pruning
    Leetcode 557. Reverse Words in a String III
    python 多维list声明时的小问题
  • 原文地址:https://www.cnblogs.com/momogua/p/8304585.html
Copyright © 2011-2022 走看看