Postgres regexp_replace:无法用第一个捕获的组替换源文本

Posted

技术标签:

【中文标题】Postgres regexp_replace:无法用第一个捕获的组替换源文本【英文标题】:Postgres regexp_replace: inability to replace source text with first captured group 【发布时间】:2021-03-05 18:42:00 【问题描述】:

使用 PostgreSQL,我无法设计正确的正则表达式模式来实现使用 regexp_replace 的 SQL 语句的所需输出。

我的源文本由几个分散的文本块组成,格式为“PU*”,后跟一个格式为“YYYY-MM”的日期字符串,例如“PU*2020-11”。这些块被不可预知的任意文本字符串(包括“PU*”的其他实例,后跟上述日期字符串格式,例如“PU*2017-07”)、空格和换行符包围。

我希望用“YYYY-MM”文本模式的第一个实例替换整个源文本。在上面的示例中,所需的输出将是“2020-11”。

目前,我的搜索模式会产生正确的替换文本来代替第一个捕获组,但不幸的是,第一个捕获组之后的所有文本也无意中出现在输出中,这不是所需的输出。

具体来说:

版本:postgres (PostgreSQL) 13.0

一个更复杂的源文本示例:

First line
Exec committee
PU*2020-08
PU*2019-09--cancelled
PU*2017-10

added by Terranze

到目前为止我的模式:

(\s|\S)*?PU\*(\d4-\d2)(\s|\S*)*

当前 SQL 语句:

select regexp_replace('First line\nExec committee; PU*2020-08\nPU*2019-09\nPU*2017-10\n\nadded by Terranze\n', '(\s|\S)*?PU\*(\d4-\d2)(\s|\S*)*', '\2') as _regex;

https://regex101.com/ 上的电流输出

2020-08

psql 上的当前输出

                              _regex                               
───────────────────────────────────────────────────────────────────
 2020-08\nPU*2019-09--cancelled\nPU*2017-10\n\nadded by Terranze\n
(1 row)

期望的输出:

2020-08

任何帮助表示赞赏。谢谢--

【问题讨论】:

【参考方案1】:

这个表达式怎么样:

'^.*?PU\*(\d4-\d2).*$'

【讨论】:

感谢您的快速回复!好吧,我意识到我在描述问题的方式上犯了一个错误。我的示例复杂源文本包含换行符,我认为将 '\n's 放在源文本中会模拟实际的换行符,但我现在意识到它没有。正则表达式引擎将这些解释为文字'\n'。 所以我将源文本更新为真正的多行,而您的模式在这种情况下不起作用。你知道另一种可能有效的模式吗?谢谢-- 对不起,我收回;您的解决方案有效!我知道 ^ 标记字符串的开头, $ 标记结尾,但我不知道为什么在这种情况下它们是必要的。 很棒的@WDock。那么,您能否将 awswer 标记为已接受。 :) 关于您的问题,首先需要 ^ 和 $ 创建一个固定的锚点,以便在字符串末尾以“最贪婪”的方式完成捕获,反之亦然一开始就接近。希望这很清楚

以上是关于Postgres regexp_replace:无法用第一个捕获的组替换源文本的主要内容,如果未能解决你的问题,请参考以下文章

使用 postgres regexp_replace() 替换字符串中的整数

Postgres regexp_replace:无法用第一个捕获的组替换源文本

正则表达式使用 postgres regexp_replace() 用单引号替换反斜杠和单引号

从 postgres 表列中删除括号,但在其中保留单词

需要使用 regexp_replace (Postgresql) 将逗号添加到数字列表中

将数据从 postgres 传输到 json 的问题