2013-06-05 22 views
0

我有一個字段message,字符串如<pika> [SOME_TEXT_WITH|ACTION] And other stuff...Postgresql的子串表達式

我希望捕捉括號內的內容。我用下面的形式:

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

但它總是失敗,同樣的ennoying錯誤消息:«無效的正則表達式:括號()不均衡»。我做錯了什麼?

回答

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所轉換的POSIX SIMILAR 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 
+0

'regexp_matches'不返回數組嗎? – greg

+0

@greg是的,這就是爲什麼我寫了'(regexp_matches(...))[1]' –

+0

Yuuu ...我不知道我們可以做到這一點......太棒了! Thx – greg

1

我認爲下面你想要做什麼:

SELECT substring(cast(message as varchar(1000)) FROM '.*\[([A-Z_\|]*)\].*' 
       ) 
FROM my_table; 
+0

您的解決方案也在工作。我不明白CAST爲什麼使正則表達式起作用。 'substring(CAST(message AS varchar)FROM'<#「[0-9a-zA-Z,:] +#」>%'FOR'#')AS my_info'起作用。編輯:我測試了一個錯誤的行。克雷格是正確的逃生焦炭。 – greg

+0

@greg。 。 。當我在SQLFiddle中測試這個時,我需要它。 –