【问题标题】:How do you escape this regular expression?你如何逃避这个正则表达式?
【发布时间】:2012-10-13 11:08:57
【问题描述】:

我在找

“医学博士” (2004)

后面有任何东西。我试过where id~'"House M\.D\." \(2004\).*'; 没有匹配项

这工作 id~'.*House M.D..*2004.*'; 但有点慢。

【问题讨论】:

  • 你真的应该在任何问题中包含 PostgreSQL 版本。这是特定于版本的。
  • @CraigRinger 很抱歉速度很慢,但我怎么才能找到呢?
  • SELECT version();。每次启动时也会打印psql,显示在 PgAdmin-III 中,显示在包列表/已安装程序列表等中。

标签: sql regex postgresql


【解决方案1】:

我怀疑您使用的是较旧的 PostgreSQL 版本,默认情况下该版本以非标准兼容的 C-escape-like 模式解释字符串,因此反斜杠被视为转义并使用。试试SET standard_conforming_strings = 'on';

根据lexical structure 关于字符串常量的文档,您可以:

  • 确保standard_conforming_strings 已打开,在这种情况下,您必须将任何单引号加倍(即' 变为'')但反斜杠不会被视为转义:

    id ~ '"House M\.D\." \(2004\)'

  • 使用非标准的、特定于 PostgreSQL 的 E'' 语法并将反斜杠加倍:

    id ~ E'"House M\\.D\\." \\(2004\\)'

PostgreSQL 9.1 及以上版本默认将standard_conforming_strings 设置为on;见the documentation

您应该在测试代码后在旧版本中打开它,因为它会使以后的更新更加容易。您可以在postgresql.conf 中全局启用它,在每个用户级别使用ALTER ROLE ... SET,在每个数据库级别使用ALTER DATABASE ... SET 或在会话级别使用SET standard_conforming_strings = on。使用SET LOCAL 将其设置在事务范围内。

【讨论】:

    【解决方案2】:

    看起来你的正则表达式没问题

    http://sqlfiddle.com/#!12/d41d8/113

    【讨论】:

    • 是的,这就是我在回答中所说的。只是指出问题不在于正则表达式,而是 OP 使用 Pg 9.0 或更早版本而没有 standard_conforming_strings 并且不允许字符串文字解析使用反斜杠。
    【解决方案3】:
    CREATE OR REPLACE FUNCTION public.regexp_quote(IN TEXT) 
      RETURNS TEXT 
      LANGUAGE plpgsql 
      STABLE 
    AS $$ 
    /******************************************************************************* 
     * Function Name: regexp_quote 
     * In-coming Param: 
     *   The string to decoded and convert into a set of text arrays. 
     * Returns: 
     *   This function produces a TEXT that can be used as a regular expression 
     *   pattern that would match the input as if it were a literal pattern. 
     * Description: 
     *   Takes in a TEXT in and escapes all of the necessary characters so that 
     *   the output can be used as a regular expression to match the input as if 
     *   it were a literal pattern. 
     ******************************************************************************/ 
    BEGIN 
      RETURN REGEXP_REPLACE($1, '([[\\](){}.+*^$|\\\\?-])', '\\\\\\1', 'g'); 
    END; 
    $$ 
    

    测试:

    SELECT regexp_quote('"House M.D." (2004)'); -- produces: "House M\\.D\\." \\(2004\\)
    

    【讨论】:

      猜你喜欢
      • 2022-01-24
      • 2019-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-24
      • 1970-01-01
      相关资源
      最近更新 更多