Регулярное выражение MySQL для эмодзи / юникода

Я хочу найти в своей базе данных любую строку, содержащую эмодзи бабочки - ? - с помощью regexp.

Например

SELECT *
     FROM   `table`
     WHERE  `text`
     REGEXP '?'

Я использую REGEXP, потому что могу найти Hello[[:space:]]world или аналогичный.

Я получаю ошибку

Got error 'nothing to repeat at offset 0' from regexp

Это работает:

SELECT *
     FROM   `table`
     WHERE  `text`
     LIKE   '%?%'

Но потом теряю возможность искать, скажем, flying[[:space:]]?

Моя подборка - utf8mb4_unicode_ci. База данных - 10.0.36-MariaDB

Если он использует utf-16, вы должны использовать суррогатную пару '\uD83E\uDD8B', в противном случае используйте кодовую точку '\U0001F98B'

user557597 08.12.2018 19:18

@sln - в вопросе используется текст в кодировке UTF-8 (шестнадцатеричный F09FA68B), а не в формате UTF-16. Не используйте коды CHARACTER SET utf16 или \u.

Rick James 08.12.2018 22:02

Это может быть кодировка текста исходного кода MySQL, что означает, что вы должны использовать кодовые точки в регулярном выражении, что всегда лучше. @RickJames - исходный текст регулярного выражения не представлен с помощью байтовый код. Они представляют собой КОДЕПИНТЫ, который устраняет двусмысленность от источника кодирования как исходного, так и целевого текстов регулярного выражения. Обычно это обрабатывается как Персонаж, тогда как целевая кодировка для этого модуля является непрозрачной фоновой задачей при запуске механизма. \uXXXX\u{XX}\x{XX} кодируют независимые конструкции CODEPOINT.

user557597 09.12.2018 12:59

@sln - \uD83E\uDD8B для MySQL составляет 10 байтов ascii. \u превращается в u. Обратите внимание на отсутствие \u на dev.mysql.com/doc/refman/8.0/en/string-literals.html. мая означает, что клиент интерпретирует кодовые точки. SELECT LENGTH('\uD83E\uDD8B'); -> 10. См. Также HEX() и CHAR_LENGTH().

Rick James 09.12.2018 19:13

@sln - Сюжет сгущается. SELECT HEX('\U+1F98B'); -> F09FA68B. (Обратите внимание на добавленный +.) Но \U+0034 действует как строка ascii. Мне нужно почесать затылок.

Rick James 09.12.2018 19:21

@RickJames - Хорошо, мало исследовал. Num 1: при использовании версии MySQL 8.0.4 или выше используется механизм регулярных выражений ICU. Num 2: необходимо избежать обратной косой черты, чтобы получить обратную косую черту для двигателя. Число 3: Нотация кодовых точек в ICU использует конструкцию \x{}. Num 4: Необходимо использовать ключевое слово REGEXP. Num 5: иногда цель находится в UTF-16, в противном случае - в UTF-8/32. Итак, если у вас есть известный mbcs, сначала преобразуйте его в 8/16/32. Поместив это на место, попробуйте это. REGEXP '\\x{D83E}\\x{DD8B}' или REGEXP '\\x{1F98B}'

user557597 10.12.2018 02:50
dbfiddle.uk/… Я выбрал MySQL версии 8. Я не думаю, что mariadb использует движок ICU, как MySQL для его регулярного выражения. Итак, удачи с этим ...
user557597 10.12.2018 03:00
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
8
855
2

Ответы 2

Честно говоря, я не знаю почему, но побег от бабочки даст желаемый результат. (По крайней мере, в моей версии MariaDB 10.3.10, которая выдавала ту же ошибку без экранирования).

SELECT * FROM `table` WHERE `text` REGEXP '\\?'

(обратите внимание на двойную обратную косую черту, первая - для экранирования обратной косой черты внутри строки, что дает регулярное выражение \?)

Интересный. Когда я пытаюсь это сделать, он находит любой текст с символом ?, а также текст с символом ?. Очень странно! Ваш ответ приближает меня, но он мне не подходит.

Terence Eden 08.12.2018 15:17

@TerenceEden: Я не могу воспроизвести проблему, см. dbfiddle.

wchiquito 08.12.2018 15:31

Эта рабочий пример использует MariaDB 10.3.11. Я использую 10.0.36. Подозреваю, поэтому.

Terence Eden 08.12.2018 15:42

Я также использовал 10.3 с той же ошибкой (хотя я получил эту ошибку только на регулярном выражении с одной бабочкой, а не с префиксом flying[[:space:]]). Может какая-то настройка сервера или подключения? Или, может быть, в моем случае PhpMyAdmin идет не так ...

Peter van der Wal 08.12.2018 15:47

Это помогло мне найти (foo|?|baz) на MariaDB 10.1.44. При переходе на (foo|\\?|baz) поиск выполнялся без ошибок, как и ожидалось. Все наборы символов (клиент, база данных и т. д.) Уже были правильно установлены в каждом случае.

Christopher Schultz 13.06.2020 16:33
SHOW VARIABLES LIKE 'char%';

Похоже, вы не сказали MySQL, какую кодировку клиент использует для символов. Лучше всего это сделать через параметры подключения или через mysqli_charset (при использовании mysqli, а не PDO).

Также запустите это в своей версии:

SELECT 'ab' REGEXP '?';

Я подозреваю, что это даст вам то же сообщение об ошибке.

Показать переменные дает character_set_client utf8mb4 character_set_connection utf8mb4 character_set_database latin1 character_set_filesystem двоичный character_set_results utf8mb4 character_set_server latin1 character_set_system utf8 character_sets_dir / usr / share / mysql / charsets / Так это выглядит правильно? Вы правы насчет ошибки в инструкции select.

Terence Eden 08.12.2018 22:36

Да, похоже, правильно. См. «Вопросительный знак» в stackoverflow.com/questions/38363566/…

Rick James 09.12.2018 02:27

Другие вопросы по теме