Regex для сопоставления с чем угодно (включая пустую строку), кроме конкретной заданной строки - PullRequest
3 голосов
/ 15 мая 2010

Я хотел бы проверить, содержит ли строка "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)'

Но REGEXP Mysql, похоже, не такой.

ADDENDUM: Спасибо David M за обобщение этого вопроса: Как преобразовать PCRE в POSIX RE?

Ответы [ 4 ]

4 голосов
/ 15 мая 2010

MySQL не имеет перспектив. Обходной путь должен сделать два теста:

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

Я использовал LIKE здесь вместо RLIKE, потому что, как только вы разбили это на части, регулярные выражения больше не нужны. Однако если вам все еще нужны регулярные выражения по другим причинам, вы все равно можете использовать эту же технику.

Обратите внимание, что это не соответствует «Канзасскому штату Канзас», как вы просили.

Обновление: если соответствие «Канзас-Канзас-Стейт» так важно, вы можете использовать это уродливое регулярное выражение, поддерживаемое MySQL:

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

Упс: я только что заметил, что Кип уже обновил свой комментарий решением, очень похожим на это.

2 голосов
/ 21 мая 2010

Более эффективно, чем это большое регулярное выражение (в зависимости, конечно, от ваших данных и качества движка)

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%'

Это имеет дополнительное преимущество, заключающееся в простоте обслуживания. Это работает не так хорошо, если Канзас распространен, а текстовые поля большие. Конечно, вы можете проверить их на своих собственных данных и рассказать нам, как они сравниваются.

2 голосов
/ 15 мая 2010

Это должно работать, при условии, что в регулярных выражениях MySQL разрешены предварительные утверждения.

/Kansas(?! State)/

Редактировать : ОК, это ужасно, но у меня это работает в Perl и не использует прогнозное утверждение:

/Kansas(([^ ]|$)| (([^S]|$)|S(([^t]|$)|t(([^a]|$)|a(([^t]|$)|t([^e]|$))))))/
1 голос
/ 15 мая 2010

Это безобразно, но вот, пожалуйста:

Возможно, вам не потребуется расширять регулярное выражение до конца, в зависимости от того, может ли ваш вклад включать что-то вроде «Мне нужно отправить этого человека на операцию в Kansas Stat!»

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)
...