有人可以解释PostgreSQL 9.2.4中regexp_matches()
的奇怪行为(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)
第二个参数是正则表达式。 $
标志着字符串的结尾
第三个参数用于标志。 g
用于“全局”,意味着该功能不会在第一场比赛时停止。
该函数似乎使用g
标志报告字符串两次的结尾,但每个定义只能存在一次。它打破了我的疑问。 :(
我错过了什么吗?
对于任何可能的字符串,我需要我的查询在末尾返回一行更多行。我希望这个查询可以完成这项工作,但它会添加两个行:
SELECT (regexp_matches('test & foo/bar', '(&|/|$)', 'ig'))[1] AS delim
我知道如何手动添加行,但我想让函数处理它。
答案 0 :(得分:1)
我不确定我要说什么,因为我不使用PostgreSQL,所以这只是我大声思考。
因为你试图匹配字符串/行$
的结尾,所以在第一种情况下结果是预期的,但是当你打开全局匹配修饰符g
并且因为匹配结束时line字符实际上并不消耗或读取输入字符串中的任何字符,然后下一个匹配尝试将从第一个字符串停止的位置开始,即在字符串的结尾处,如果它保持这样的话,这将导致无限循环PostgreSQL引擎可能能够检测到这一点并将其停止以防止崩溃或无限循环。
我在RegexBuddy中使用POSIX ERE风格测试了相同的表达式,导致程序无响应并崩溃,这就是我推理的原因。
答案 1 :(得分:1)
看起来它是PostgreSQL中的一个错误。我确认它已在9.3.8中修复。查看发行说明,我看到可能的参考文献:
允许通过查询提前终止正则表达式运算符 取消请求(Tom Lane)
这可以防止病理性正则表达的情况 可以长时间不间断地锁定服务器进程。
修复错误搜索最短的第一个正则表达式匹配项 (汤姆莱恩)
当允许的迭代次数为时,匹配通常会失败 受限于?量词或约束表达。
感谢Erwin将其缩小到9.3.x。
答案 2 :(得分: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/'
。
并且返回实际的最终字符并不完美。更喜欢空字符串。
答案 3 :(得分:0)
同样的情况发生在例如最近我遇到同样问题的C#中,所以我认为这是正则表达式的正常行为
这是因为$
不代表特定的标志,而是代表特定的位置
所以$
并不真正匹配任何东西,解析器的位置保持在同一位置
你需要改变你的约定;
测试可以使用^$