0

有人可以解释regexp_matches()PostgreSQL 9.2.4 中的这种奇怪行为(9.1.9 中的结果相同):

db=# SELECT regexp_matches('test string', '$') AS end_of_string;
 end_of_string
---------------
 {""}
(1 row)

db=# SELECT regexp_matches('test string', '$', 'g') AS end_of_string;
 end_of_string
---------------
 {""}
 {""}
(2 rows)

-> SQLfiddle 演示。

第二个参数是一个正则表达式。$标记字符串的结尾。
第三个参数用于标志。g用于“全局”,这意味着该功能不会在第一次匹配时停止。

该函数似乎使用标志两次报告字符串的结尾,但每个定义g只能存在一次。它打破了我的查询。:(
我错过了什么吗?


对于任何可能的字符串,我需要我的查询在最后返回一行。我希望这个查询能够完成这项工作,但它添加了行:

SELECT (regexp_matches('test & foo/bar', '(&|/|$)', 'ig'))[1] AS delim

我知道如何手动添加一行,但我想让函数处理它。

4

4 回答 4

1

我不确定我要说什么,因为我不使用 PostgreSQL,所以这只是我在大声思考。

由于您正在尝试匹配 string/line 的结尾$,因此在第一种情况下,结果是预期的,但是当您打开全局匹配修饰符g并且因为匹配行尾字符实际上不会消耗或读取任何字符输入字符串,然后下一次匹配尝试将从第一个停止的地方开始,即在字符串的末尾,如果它继续这样下去,这将导致无限循环,因此 PostgreSQL 引擎可能能够检测到这一点并停止它以防止崩溃或无限循环。

我在具有 POSIX ERE 风格的 RegexBuddy 中测试了相同的表达式,它导致程序变得无响应并崩溃,这就是我推理的原因。

于 2013-08-12T14:30:51.413 回答
1

例如在 C# 中也会发生同样的情况,我最近遇到了同样的问题,所以我认为这是正则表达式的正常行为

这是因为$不代表特定的符号,而是代表特定的位置,所以$实际上不匹配任何东西,并且解析器的位置保持在相同的位置

你需要稍微改变一下你的约定;

测试你可以使用的空字符串^$

于 2014-01-11T17:55:59.940 回答
1

看起来这是 PostgreSQL 中的一个错误。我确认它已在 9.3.8 中修复。查看发行说明,我看到了可能的参考:

9.3.4

  • 允许通过查询取消请求提前终止正则表达式运算符 (Tom Lane)

    这可以防止病态正则表达式可能长时间不间断地锁定服务器进程的情况。

9.3.6

  • 修复对最短优先正则表达式匹配的错误搜索 (Tom Lane)

    当允许的迭代次数受 ? 限制时,匹配通常会失败。量词或绑定表达式。

感谢 Erwin 将其缩小到 9.3.x。

于 2016-06-24T13:16:13.637 回答
0

这是 Postgres 9.3 中修复的错误。请参阅已接受的答案。


对于 Postgres 9.2 或更早版本:对于我的情况,一个不错的解决方法是改用表达式.$- 在最后一个字符处匹配任何字符串:

WITH x(id, t) AS (
   VALUES
    (1, 'test & foo/bar')
   ,(2, 'test')
   ,(3, '')            -- empty string
   ,(4, 'test & foo/') -- other branch as last character
   )
SELECT id, (regexp_matches(t, '(&|/|.$)', 'ig'))[1] AS delim
FROM   x;

但它对于空字符串失败。
如果最后一个字符恰好匹配另一个分支,它就会失败。喜欢:'foo/bar/'
并且返回实际的最终字符并不完美。一个空字符串会更可取。

-> SQLfiddle。

于 2013-08-12T14:58:40.113 回答