【问题标题】:Hex characters in regexp matching in mysqlmysql中正则表达式匹配中的十六进制字符
【发布时间】:2010-02-04 12:13:56
【问题描述】:

我发现 mysql 的行为非常奇怪。 下面的选择返回0:

SELECT CONVERT('a' USING BINARY) REGEXP '[\x61]'

但是,下面的语义相同的选择返回 1:

SELECT CONVERT('a' USING BINARY) REGEXP '[\x61-\x61]'

你知道这里发生了什么吗? 我已经在 mysql 5.0.0.3031 和 4.1.22 中测试过

当二进制字符串以 utf8 编码时,我需要十六进制字符来创建匹配的正则表达式。这种正则表达式的 perl 版本可以在 w3c site 上找到。如下所示:

$field =~
      m/\A(
         [\x09\x0A\x0D\x20-\x7E]            # ASCII
       | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
       |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
       | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
       |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
       |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
       | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
       |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
      )*\z/x;

【问题讨论】:

标签: mysql regex


【解决方案1】:

这也匹配:

SELECT CONVERT('a' USING BINARY) REGEXP '[1-\x]'

原因是\x 被解释为xa 介于1x 之间。正则表达式的其余部分只是与此处无关的普通字符,因为它们已经在 [1-x] 范围内。

SELECT CONVERT('0' USING BINARY) REGEXP '[\x61-\x61]' -- Fails, because 0 < 1.
SELECT CONVERT('1' USING BINARY) REGEXP '[\x61-\x61]' -- Succeeds: inside [1-x].
SELECT CONVERT('2' USING BINARY) REGEXP '[\x61-\x61]' -- Succeeds: inside [1-x].
...
SELECT CONVERT('w' USING BINARY) REGEXP '[\x61-\x61]' -- Succeeds: inside [1-x].
SELECT CONVERT('x' USING BINARY) REGEXP '[\x61-\x61]' -- Succeeds: inside [1-x].
SELECT CONVERT('y' USING BINARY) REGEXP '[\x61-\x61]' -- Fails, because y > x.

我不确定你想要实现什么,但如果你想要十六进制字符,你可以使用 hex 函数:

SELECT HEX('a')
61

【讨论】:

【解决方案2】:

要在 mysql 中编写像 [\x61-\x65] 这样的正则表达式,您可以在 concat 中使用十六进制值:

SELECT CONVERT('a' USING BINARY) REGEXP CONCAT('[', 0x61, '-', 0x65, ']')

【讨论】:

    【解决方案3】:

    大声笑...根据以上内容,您可以只使用打印字符。这对我有用。我想让它匹配不在美国键盘上的字符,以下表达式适用于 MySQL 5.1:

    [^ -~]
    

    这将与

    做同样的事情
    [^\x20-\x7E]
    

    【讨论】:

    • +1 好点!另一方面,如果数字大于 0x7E,它可能会变得很棘手
    • 它几乎可以满足我的所有需求。 ...AND l.Description NOT RLIKE "[\n“”’¿½–é° ±…•—♀¾‘¢¼®ç²º àóªáíñ·­]+"
    【解决方案4】:

    我想检查 latin-1 列中的 UTF-8 编码字符,扩展了 Puggan Se 给我的答案:

    mysql> SELECT count(*) from myTable where CONVERT(myCol USING BINARY) REGEXP CONCAT('[',0xF0,'-',0xFF,']','[', 0x80, '-', 0xBF, ']' ) 限制 3; +----------+ |计数(*) | +----------+ | 0 | +----------+ 一组中的 1 行(0.54 秒) mysql> SELECT count(*) from myTable where CONVERT(myCol USING BINARY) REGEXP CONCAT('[',0xE0,'-',0xEF,']','[', 0x80, '-', 0xBF, ']' ) 限制 3; +----------+ |计数(*) | +----------+ | 0 | +----------+ 一组中的 1 行(0.53 秒) mysql> SELECT count(*) from myTable where CONVERT(myCol USING BINARY) REGEXP CONCAT('[',0xC2,'-',0xDF,']','[', 0x80, '-', 0xBF, ']' ) 限制 3; +----------+ |计数(*) | +----------+ | 0 | +----------+ 1 行一组(0.50 秒) mysql>

    当我不计算行数时,限制就在那里,反转正则表达式中的最后一个范围向我表明那里实际上有扩展字符(让我相信正则表达式有效,因为它没有找到任何损坏的数据我呢)。 参考:https://www.fileformat.info/info/unicode/utf8.htm

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-27
      • 2016-12-30
      • 2019-02-28
      • 2012-11-28
      • 2021-02-13
      • 1970-01-01
      • 2016-12-03
      相关资源
      最近更新 更多