【问题标题】:mysql regex get position of matched first alphabetic charactermysql 正则表达式获取匹配的第一个字母字符的位置
【发布时间】:2014-09-10 22:56:45
【问题描述】:

我有一个带有 REGEXP 的 mysql 查询,它匹配字段的开头与“A”、“An”和“The”,如果匹配,则后跟空格,然后从第一个空格的开头修剪字段,然后我匹配字段的开头带有特殊字符,如 (','',[:space:]) 如果是,则修剪所有前导特殊字符。 Mysql 查询是用CASE 像这样:

CASE
  WHEN field_data_field_display_title_field_display_title_value REGEXP '(^(A|An|The)[[:space:]])' = 1 THEN
  TRIM(SUBSTR(field_data_field_display_title_field_display_title_value , INSTR(field_data_field_display_title_field_display_title_value ,' ')))
  WHEN field_data_field_display_title_field_display_title_value REGEXP '(^[\"\'[:space:]])' = 1 THEN
    TRIM(SUBSTR(field_data_field_display_title_field_display_title_value ,2))
  ELSE field_data_field_display_title_field_display_title_value
END

我无法修剪所有前导特殊字符,但我可以通过在 SUBSTR 函数中传递“2”来修剪第一个前导特殊字符。由于mysql不支持捕获组,所以我无法在捕获组中获取匹配值。

所以我的问题是如何使用 mysql 查询获得字段中第一个字母字符的位置,以便我可以在 SUBSTR 函数中传递该位置以修剪所有前导特殊字符。我尝试使用 [:alpha:] 类,例如:

TRIM(SUBSTR(field_data_field_display_title_field_display_title_value ,
 INSTR(field_data_field_display_title_field_display_title_value ,[:alpha:])))

但它给出了 mysql 语法错误。或者任何人都可以向我建议任何其他方法来修剪所有前导特殊字符。

提前致谢!

【问题讨论】:

标签: mysql regex string trim


【解决方案1】:

如果你更新你的 MySql 版本 (8.0+:) 你可以使用REGEXP_INSTR 函数。

SELECT
  REGEXP_INSTR('500 Oracle Parkway, Redwood Shores, CA',
               '[^ ]+', 1, 6) "REGEXP_INSTR"
  FROM DUAL;

REGEXP_INSTR
------------
          37

或者如果更新 MySql 版本不是一个选项,您可以尝试使用用户定义函数 (UDF),例如 mysql-udf-regexp。我没用过,文档也不清楚如何安装。

【讨论】:

    【解决方案2】:

    没有正则表达式匹配函数来报告字符串中的位置,MySQL 中也没有任何正则表达式替换函数。

    (更新:MySQL 8.0 现在支持more regex functions,但它们在早期版本的 MySQL 中不可用。)

    如果您知道要搜索特定单词的简短列表,则可以在多个匹配项中选择最少的位置:

    SUBSTRING(field_data_field_display_title_field_display_title_value,
      LEAST(
        INSTR(field_data_field_display_title_field_display_title_value, 'A '),
        INSTR(field_data_field_display_title_field_display_title_value, 'An '),
        INSTR(field_data_field_display_title_field_display_title_value, 'The ')
      )
    )
    

    在 SQL 中进行子字符串匹配或替换通常很尴尬,因为 SQL 从根本上来说就是将列视为不可约的数据。任何处理子字符串的函数都是语言的扩展,而不是内置的。

    如果您希望通过字符串函数更好地处理,将整个字符串提取到应用程序中并使用更丰富的函数集编写代码会更容易。虽然我知道如果您描述的子字符串操作的原因是影响查询结果的表达式,例如限制行的 WHERE 子句或排序的 ORDER BY 子句,这是不切实际的。

    如果是这样,那么更好的解决方案是更改存储字符串的方式。用特殊字符分割前缀部分中的字符串,然后为以 A、An 或 The 开头的部分分隔一列,然后甚至可能是第三列,其中包含您不想成为其中一部分的尾随文本正文。

    拆分它的好处是处理主字符串的 SQL 表达式要简单得多,您甚至可以正常索引它以获得某些查询的大量性能。

    【讨论】:

    • 谢谢@BillKarwin。是的,我做了类似的事情。在答案字段中发布我的答案。
    【解决方案3】:

    我正在使用我在 ORDER BY 子句中发布的 mysql sn-p 对数据进行排序。由于我有一小部分要删除的匹配项,所以我遵循了@BillKarwin 的建议。 查询中的 ORDER BY 子句变成类似

    ORDER BY 
      CASE
        WHEN field_data_field_display_title_field_display_title_value REGEXP '^(A|An|The)[[:space:]]' = 1 THEN
          TRIM(SUBSTR(field_data_field_display_title_field_display_title_value , INSTR(field_data_field_display_title_field_display_title_value ,' ')))
        WHEN field_data_field_display_title_field_display_title_value REGEXP '^[\']' = 1 THEN
          TRIM(LEADING '\'' FROM field_data_field_display_title_field_display_title_value)
        WHEN field_data_field_display_title_field_display_title_value REGEXP '^[[:space:]]' = 1 THEN
          TRIM(LEADING ' ' FROM field_data_field_display_title_field_display_title_value)
        WHEN field_data_field_display_title_field_display_title_value REGEXP '^[\"]' = 1 THEN
          TRIM(LEADING '"' FROM field_data_field_display_title_field_display_title_value)
        ELSE field_data_field_display_title_field_display_title_value
      END ASC
    

    【讨论】:

      猜你喜欢
      • 2011-12-04
      • 2013-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多