MySQL REGEXP с границей слова после косой черты

У меня есть несколько URL без http:// в таблице базы данных:

        url
row #1: 10.1.127.4/
row #2: 10.1.127.4/something

Теперь следующий фильтр дает мне строку №2 - отлично:

SELECT * FROM mytable WHERE url REGEXP '[[:<:]]10.1.127.4/something[[:>:]]'

Но следующий фильтр не дает мне строку № 1, но не так ли?

SELECT * FROM mytable WHERE url REGEXP '[[:<:]]10.1.127.4/[[:>:]]'

Я должен отметить, что также экранирование прямой косой черты через обратную косую черту не возвращает искомую строку #1:

SELECT * FROM mytable WHERE url REGEXP '[[:<:]]10.1.127.4\/[[:>:]]'

3 ответа

Решение

Выяснилось, что [[:>:]] ожидает символ слова слева, и наоборот для [[:<:]]

Простые тесты подтверждают, что:

SELECT 'bla,,123' REGEXP '[[:<:]]bla,[[:>:]]' -- no match
SELECT 'bla,,123' REGEXP '[[:<:]]bla[[:>:]]' -- match
SELECT 'bla,,123' REGEXP '[[:<:]]bla,,123[[:>:]]' -- match

Я думаю, что в этом смысле документация имеет смысл, и я неправильно понял это на протяжении нескольких лет:

[...] границы слова. Они соответствуют началу и концу слов, [...]

Итак, граница слова ожидает

  1. несловесный символ с одной стороны
  2. и символ слова на другой стороне

Согласно документам: http://dev.mysql.com/doc/refman/5.7/en/regexp.html

[[:<:]], [[:>:]]

Эти маркеры обозначают границы слов. Они соответствуют началу и концу слов соответственно. Слово - это последовательность символов слова, которой не предшествуют или не следуют символы слова. Символ слова - это буквенно-цифровой символ в классе alnum или знак подчеркивания (_).

/ не является членом alnum, поэтому это не граница слова.

SELECT * FROM mytable WHERE mycolumn REGEXP "[[:<:]][0-9]{1,3}\\.([0-9]{1,3}.?){3}((\\/)?[^ ]*)?[[:>:]]";

[[:<:]][0-9]{1,3}\.([0-9]{1,3}.?){3}((\/)?[^ ]*)?[[:>:]]

Assert position at the beginning of a word (position followed by but not preceded by an ASCII letter, digit, or underscore) «[[:<:]]»
Match a single character in the range between “0” and “9” «[0-9]{1,3}»
   Between one and 3 times, as few or as many times as needed to find the longest match in combination with the other quantifiers or alternatives «{1,3}»
Match the character “.” literally «\.»
Match the regex below and capture its match into backreference number 1 «([0-9]{1,3}.?){3}»
   Exactly 3 times «{3}»
      You repeated the capturing group itself.  The group will capture only the last iteration.  Put a capturing group around the repeated group to capture all iterations. «{3}»
   Match a single character in the range between “0” and “9” «[0-9]{1,3}»
      Between one and 3 times, as few or as many times as needed to find the longest match in combination with the other quantifiers or alternatives «{1,3}»
   Match any single character that is NOT a line break character (line feed) «.?»
      Between zero and one times, as few or as many times as needed to find the longest match in combination with the other quantifiers or alternatives «?»
Match the regex below and capture its match into backreference number 2 «((\/)?[^ ]*)?»
   Between zero and one times, as few or as many times as needed to find the longest match in combination with the other quantifiers or alternatives «?»
   Match the regex below and capture its match into backreference number 3 «(\/)?»
      Between zero and one times, as few or as many times as needed to find the longest match in combination with the other quantifiers or alternatives «?»
      Match the character “/” literally «\/»
   Match any single character that is NOT present in the list below and that is NOT a line break character (line feed) «[^ ]*»
      Between zero and unlimited times, as few or as many times as needed to find the longest match in combination with the other quantifiers or alternatives «*»
      The literal character “ ” « »
Assert position at the end of a word (position preceded by but not followed by an ASCII letter, digit, or underscore) «[[:>:]]»
Другие вопросы по тегам