匹配MySQL中的正则表达式,包含条件的重复单词不包括括号

问题描述:

我遇到查询问题。我使用mysql作为数据库。我想用一个正则表达式的结果我预期匹配,并且表是匹配MySQL中的正则表达式,包含条件的重复单词不包括括号

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  | 

我试图S上的查询Ø远

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

+0

对不起..错误的打字 – muhnizar 2014-09-02 02:32:15

+0

在第二个期望中,除了空格外,你的意思是什么 – hwnd 2014-09-02 02:35:16

+0

- 它没有在ID = 2中显示结果,因为在2之后有1(2之后的字符必须是varchar) - 它会在ID = 3中显示结果,因为之前/之前2只有空白(除了在空白之前/之前) – muhnizar 2014-09-02 02:39:56

我提出这个表达式:

^([^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 s在字符串中。

有可能是一种方法用一个正则表达式来做到这一点,但我觉得它更容易使用三:

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' 
    ); 
+0

我仍然得到错误的结果 – muhnizar 2014-09-02 02:42:32