1

我有一个message带有字符串的字段,例如<pika> [SOME_TEXT_WITH|ACTION] And other stuff....

我希望捕捉括号内的内容。我使用以下表格:

SELECT 
  substring(message FROM '%> \[#"[A-Z_\|]+#"\] %' FOR '#') AS my_info 
FROM my_table;

但它总是以同样令人讨厌的错误消息失败:«无效的正则表达式:括号()不平衡»。我做错了什么?

4

2 回答 2

2

就个人而言,我会使用与 perl 兼容的现代正则表达式,而不是可怕的 POSIX 式正则表达式:

regress=> SELECT (regexp_matches('<pika> [SOME_TEXT_WITH|ACTION] And other stuff...', '\[(.*?)\]'))[1];
    regexp_matches     
-----------------------
 SOME_TEXT_WITH|ACTION
(1 row)

如果你想使用 POSIX 语法,你必须一致地使用相同的转义,而不是\在某些地方和#其他地方。例如:

regress=> SELECT substring(
            '<pika> [SOME_TEXT_WITH|ACTION] And other stuff...' 
            FROM '%#"#[%#]#"%' FOR '#'
          );
        substring        
-------------------------
 [SOME_TEXT_WITH|ACTION]
(1 row)

文档并没有很清楚地说明捕获运算符实际上是<ESCAPECHAR>",而不是#"具体。这同样有效,使用常规反斜杠转义:

regress=> SELECT substring(
              '<pika> [SOME_TEXT_WITH|ACTION] And other stuff...' 
              FROM '%\"\[%\]\"%' FOR '\'
          );
        substring        
-------------------------
 [SOME_TEXT_WITH|ACTION]
(1 row)

奇怪错误的原因是 PostgreSQL 在幕后将 POSIXSIMILAR TO样式表达式转换为真正的正则表达式。您的混合转义正则表达式:

'%> \[#"[A-Z_\|]+#"\] %' FOR '#'

正在变成类似的东西:

'.*> \\[([A-Z_\\|]+)\\] .*'

导致:

regress=> SELECT (regexp_matches('<pika> [SOME_TEXT_WITH|ACTION] And other stuff...', '.*> \\[([A-Z_\\|]+)\\] .*'))[1];
ERROR:  invalid regular expression: parentheses () not balanced
于 2013-06-05T13:37:52.973 回答
1

我认为以下内容可以满足您的要求:

SELECT substring(cast(message as varchar(1000)) FROM '.*\[([A-Z_\|]*)\].*'
                )
FROM my_table;
于 2013-06-05T13:39:44.287 回答