【问题标题】:Use SQL REGEXP (mariadb) for filter in where with special characters in Laravel [duplicate]使用SQL REGEXP(mariadb)在Laravel中使用特殊字符进行过滤[重复]
【发布时间】:2021-09-13 08:59:31
【问题描述】:

mariadb 版本10.4

$query->where('column', 'REGEXP', '[[:<:]]'.$string.'[[:>:]]');

此查询仅提供整个单词的搜索,并且没有特殊字符也可以正常工作。

示例

搜索行:
foo (bar baz)
过滤器:
$string = "(bar";
$query->where('column', 'REGEXP', '[[:<:]]'.$string.'[[:>:]]');
错误:
SQLSTATE[42000]: Syntax error or access violation: 1139 Got error 'missing )

现在我尝试使用addcslashespreg_quote。我成功地用preg_quote 转义了( 字符,但过滤器不适用于该字符串,因为过滤器适用于整个单词。

任何关于更好地过滤整个单词的建议也将不胜感激。

再举一个例子

搜索行:
foo(bar baz
过滤器:
$filter = 'foo(bar';
$query->where('column', 'REGEXP', '[[:<:]]'.$string.'[[:>:]]');

如果( 将被转义,则搜索将不起作用

【问题讨论】:

  • whereRaw() 工作吗?
  • 同样的结果。谢谢!
  • 也许这对你有帮助:stackoverflow.com/a/46627403/7451109
  • '[[:&lt;:]]\\\\(bar[[:&gt;:]]' 工作吗?
  • 同样的结果@Olivier

标签: php laravel mariadb mysql-regexp


【解决方案1】:

REGEXP 字符串中有很多具有特殊含义的标点符号。 ( 只是其中之一。

如果目标是搜索带有尾随“单词边界”的 4 个字符 (bar,那么其中之一可能会起作用 -- 取决于 MySQL/MariaDB 的版本 以及从您的应用程序到服务器需要什么转义:

\(bar[[:>:]]
\\(bar[[:>:]]
\\\\(bar[[:>:]]
[(]bar[[:>:]]

\(bar\b
\\(bar\\b
\\\\(bar\\\\b
[(]bar\b
[(]bar\\b
[(]bar\\\\b

无论如何你的应用程序必须做一些转义。鉴于此,可能删除标点符号会更好:

[[:<:]]bar[[:>:]]
\bbar\b
\\bbar\\b
\\\\bbar\\\\b

考虑也使用LIKE "(bar"

考虑同时使用FULLTEXT 索引

MATCH(col) AGAINST("bar" IN BOOLEAN MODE)

为了获得最佳性能,这可能是最好的(使用 FULLTEXT 索引):

MATCH(col) AGAINST("bar" IN BOOLEAN MODE)
AND col LIKE "(bar"

【讨论】:

  • 感谢您的回答!我明天去看看。
【解决方案2】:

试试这个:$string = '\(bar';

您可以随时在此处检查您的正则表达式模式:https://regex101.com/

【讨论】:

  • 我用preg_quoteaddcslashes 做到了。但这不是我需要的。
【解决方案3】:

如您所见,您正在使用的 ICU 正则表达式库认为括号很特殊,并且需要 double 斜线转义。使用 add_slashes() 没有用处,因为它会在非 ICU 的其他库需要的地方添加斜杠,并且可能会给您一个不适合它的字符串(例如,它不会转义圆括号)。

escapeshellcmd() 可能会更好,因为圆括号和方括号碰巧都是 s​​hell 元字符,但美元符号和井号也是如此,这可能会咬你一口稍后回来。

更简单的解决方案是手动替换您需要的四个字符(实际上是 三个、( ) [,但为了完整起见...)。

$string = preg_replace(
    '#([(\\[\\])])#', 
    '\\\\\\\\\1', // Hilarious, isn't it?
    $string
);

$query->where('column', 'REGEXP', '[[:<:]]'.$string.'[[:>:]]');

【讨论】:

    猜你喜欢
    • 2011-08-02
    • 2020-01-07
    • 2015-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多