【问题标题】:Postgres Regex Negative LookaheadPostgres 正则表达式负前瞻
【发布时间】:2017-10-08 02:24:59
【问题描述】:

场景:匹配除字符串“J01FA09”之外的任何以“J01”开头的字符串。

我很困惑为什么下面的代码什么都不返回:

SELECT 1
WHERE
    '^J01(?!FA09).*' ~ 'J01FA10'

当我在 regexr.com 上看到它正在工作时(我意识到有不同风格的正则表达式,这可能是网站正常工作的原因)。

我已在postgres documentation 中确认,虽然支持负面展望。

表 9-15。正则表达式约束

(?!re) 否定前瞻匹配任何没有子字符串的点 匹配重新开始(仅限 ARE)。前瞻约束不能包含 反向引用(参见第 9.7.3.3 节),以及其中的所有括号 被认为是非捕获的。

【问题讨论】:

  • 您不需要正则表达式。使用旧好的LIKEAND NOT...
  • 只是为了确定您的表中是否有任何行?因为看起来您确实写了SELECT 1 WHERE TRUE,只要有任何行,它就应该工作
  • @Daniel,请检查我的回答。
  • 右侧操作数...如此明显。我意识到我的确切示例不需要正则表达式,但这是更大图景的一部分。
  • @Xyzk 这个非常简单的例子不需要 FROM 子句或表格。它只是用来测试正则表达式

标签: regex postgresql


【解决方案1】:

匹配除字符串“J01FA09”之外的任何以“J01”开头的字符串。

你可以不用正则表达式

WHERE s LIKE 'J01%' AND s != 'J01FA09'

这里,LIKE 'J01%' 需要一个以 J01 开头的字符串,然后可以有任何字符,s != 'J01FA09' 将过滤掉匹配项。

如果你想用正则表达式实现同样的效果,请使用

WHERE s ~ '^J01(?!FA09$)'

^ 匹配字符串的开头,J01 匹配文字 J01 子字符串,(?!FA09$) 断言紧跟在 J01 之后没有 FA09 后跟字符串位置的结尾。如果出现FA09 且后面有字符串结尾,则不返回匹配项。

online demo

CREATE TABLE table1
    (s character varying)
;

INSERT INTO table1
    (s)
VALUES
    ('J01NNN'),
    ('J01FFF'),
    ('J01FA09'),
    ('J02FA09')
;
SELECT * FROM table1 WHERE s ~ '^J01(?!FA09$)';

SELECT * FROM table1 WHERE s LIKE 'J01%' AND s != 'J01FA09';

【讨论】:

  • 标记为答案,因为您添加了我还没有看到的字符串片段 '$' 的结尾。我最大的问题是我愚蠢的测试用例交换了操作数方面。
  • @Daniel:是的,另一个改进是你实际上不需要.*,因为使用~ 执行的正则表达式检查不需要完整的字符串匹配(与LIKESIMILAR TO 需要整个字符串匹配的模式)。
【解决方案2】:

RE 是右侧操作数:

SELECT 1
WHERE 'J01FA10' ~ '^J01(?!FA09)';

 ?column? 
----------
        1
(1 row) 

【讨论】:

  • 但是,使用这种模式,OP 将无法获得所需的结果。
  • @WiktorStribiżew - 我不知道 OP 将如何使用它,但这很好用。
  • 非常感谢您指出我的操作数方面的明显缺陷。在我将它放入更复杂的代码之前,这主要是让我无法将这个简单的展望工作。
  • 我认为最初的问题只是缺少负前瞻中的结束锚($)。
猜你喜欢
  • 2021-10-11
  • 2011-10-14
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多