匹配MySQL中的Regex,重复单词,条件不包括括号

时间:2014-09-02 02:25:09

标签: mysql sql regex

我遇到了查询问题。我使用mysql作为DB。我想使用REGEX来匹配我期望的结果和表是

table A

----------------------------------
|   ID  | Description            |
----------------------------------
|   1   |  new 2 new 2 new 2 new |
|   2   |   new 21 new 2 new     |
|   3   |   new 2th 2 (2/2)      |
|   4   |   2new 2new (2/2)      |
|   5   |   new2 new 2new        |

我预期的结果   - 数字2只能显示两次
  - 2之前/之后的字符必须是varchar(除了空白之后)
  - 特殊条件:具有模式“(数字/数字)”的任何数字,如ID = 3且ID = 4是可接受的


|   ID  | Description           |
---------------------------------
|   3   |   new 2th 2 (2/2)      |
|   4   |   2new 2new (2/2)      |
|   5   |   new2 new 2new        |  

到目前为止我尝试过的查询

http://sqlfiddle.com/#!2/a227b/2

2 个答案:

答案 0 :(得分:0)

使用一个正则表达式可能有一种方法可以做到这一点,但我发现使用三个更容易:

select *
from a
where description regexp '[a-zA-Z ]+[0-9]+[a-zA-Z ]+[0-9]+' and
      (description not regexp '[0-9]+[^0-9]+[0-9]+[^0-9]+[0-9]+' or
       description regexp '[0-9]+[^0-9]+[0-9]+[^0-9]+[0-9]+/[0-9]+'
      );

编辑:

我没有意识到目标仅针对2,而不是任何数字。这符合您的规则,但不符合您的结果(4不属于):

select *
from a
where description regexp '[a-zA-Z ]+[2]+[a-zA-Z ]+[2]+' and
      (description not regexp '[2]+[^0-9]+[2]+[^0-9]+[2]+' or
       description regexp '[2]+[^0-9]+[2]+[^0-9]+2/2'
      );

答案 1 :(得分:0)

我提出这个正则表达式:

^([^2]|[[:<:]][0-9]+/[0-9]+[[:>:]])*([[:<:]]|[a-z])2([[:>:]]|[a-z])([^2]|[[:<:]][0-9]+/[0-9]+[[:>:]])+([[:<:]]|[a-z])2([[:>:]]|[a-z])([^2]|[[:<:]][0-9]+/[0-9]+[[:>:]])*$

它有点长,但它允许更灵活,因为这些字符串也被视为“有效”:

(2/2) 2new 2new
2new (2/2) 2new (2/2)

代码

SELECT
    *
FROM
    A
WHERE 
    description REGEXP '^(([^2]+|[[:<:]][0-9]+/[0-9]+[[:>:]])*2([[:>:]]|[a-z])){2}([^2]+|[[:<:]][0-9]+/[0-9]+[[:>:]])*$'

SQLFiddle

正则表达式细分

正则表达式实际上使用了许多重复部分,所以这就是为什么它有点长:

^                                        # Beginning of string

(                                        # Open repeat group
   ([^2]+|[[:<:]][0-9]+/[0-9]+[[:>:]])*  # Any characters. See #1
  2                                      # 2
  ([[:>:]]|[a-z])                        # Word boundary or alphabet/letter. See #2
){2}                                     # Close repeat group and repeat 2 times

([^2]+|[[:<:]][0-9]+/[0-9]+[[:>:]])*     # Any characters. See #1

$

详细分类

  • <强>#1

    (           # Open group
    
      [^2]+     # Any characters except 2
    
    |           # OR
    
      [[:<:]]   # Open word boundary
      [0-9]+    # Any numbers
      /         # Forward slash
      [0-9]+    # Any numbers
      [[:>:]]   # Close word boundary
    
    )*          # Close group and repeat any number of times
    
  • <强>#2

    (           # Open group
      [[:>:]]   # Word boundary
    |           # Or
      [a-z]     # Letter/alphabet
    )           # Close group
    

单词边界与单词的开头和结尾相匹配。这里一个单词的定义是一系列字母,数字和下划线字符。

[[:<:]]是一个开头的单词边界,因此在单词的开头匹配。

[[:>:]]是一个开头的单词边界,因此在一个单词的末尾匹配。

它们的使用可确保2(以及数字/数字部分)不被其他数字包围(例如,使21失败)或计算2如果你有例如21/4作为字符串中两个2的计数。