正则表达式匹配除特定给定字符串之外的任何内容(包括空字符串)

时间:2010-05-14 20:08:25

标签: sql mysql regex pcre

我想测试一个字符串是否包含"Kansas"后跟" State"以外的任何内容。

示例:

"I am from Kansas"          true
"Kansas State is great"     false
"Kansas is a state"         true
"Kansas Kansas State"       true
"Kansas State vs Kansas"    true
"I'm from Kansas State"     false
"KansasState"               true

对于PCRE,我相信答案是:

'Kansas(?! State)'

但Mysql的REGEXP似乎并不喜欢。

ADDENDUM:感谢David M对此问题的概括: How to convert a PCRE to a POSIX RE?

4 个答案:

答案 0 :(得分:4)

MySQL没有前瞻性。解决方法是进行两项测试:

WHERE yourcolumn LIKE '%Kansas%'
  AND yourcolumn NOT LIKE '%Kansas State%'

我在这里使用LIKE而不是RLIKE,因为一旦你将它拆分成这样,就不再需要正则表达式了。但是,如果由于其他原因仍然需要正则表达式,您仍然可以使用相同的技术。

请注意,这与您要求的“堪萨斯州堪萨斯州”不符。

更新:如果匹配“堪萨斯州堪萨斯州”非常重要,那么你可以使用MySQL支持的这个丑陋的正则表达式:

'Kansas($|[^ ]| ($|[^S])| S($|[^t])| St($|[^a])| Sta($|[^t])| Stat($|[^e]))'

哎呀:我刚刚注意到Kip已经用一个非常类似的解决方案更新了他的评论。

答案 1 :(得分:2)

这应该有效,假设在MySQL正则表达式中允许前瞻性断言。

/Kansas(?! State)/

编辑:好的,这非常难看,但它在Perl中适用于我,并且不使用预见断言:

/Kansas(([^ ]|$)| (([^S]|$)|S(([^t]|$)|t(([^a]|$)|a(([^t]|$)|t([^e]|$))))))/

答案 2 :(得分:2)

比大型正则表达式更高效(当然,取决于您的数据和引擎的质量)

WHERE col LIKE '%Kansas%' AND
  (col NOT LIKE '%Kansas State%' OR
  REPLACE(col, 'Kansas State', '') LIKE '%Kansas%')

如果堪萨斯州通常以“堪萨斯州”的形式出现,你可能会发现这更好:

WHERE col LIKE '%Kansas%' AND
  REPLACE(col, 'Kansas State', '') LIKE '%Kansas%'

这具有易于维护的附加优点。如果堪萨斯很常见且文本字段很大,那么它的效果就不那么好了。当然,您可以根据自己的数据测试这些数据并告诉我们他们的比较方式。

答案 3 :(得分:1)

这很难看,但是你走了:

您可能不需要将正则表达式一直扩展到最后,具体取决于您的输入是否包含“我需要让这个人在堪萨斯统计中接受手术!”

mysql> select x,x RLIKE 'Kansas($|[^ ]| ($|[^S])| S($|[^t])| St($|[^a])| Sta($|[^t])| Stat($|[^e]))' AS result from examples;
+------------------------+--------+
| x                      | result |
+------------------------+--------+
| I am from Kansas       |      1 |
| Kansas State is great  |      0 |
| Kansas is a state      |      1 |
| Kansas Kansas State    |      1 |
| Kansas State vs Kansas |      1 |
| I'm from Kansas State  |      0 |
| KansasState            |      1 |
+------------------------+--------+
7 rows in set (0.00 sec)