PostgreSQL如何用正则提取仅含-特殊字符且排除指定停用词的单词
问题解决方法
方案1:使用regexp_matches直接提取合法单词(更简洁,推荐)
直接匹配所有符合规则的单词,再过滤停用词即可,查询语句如下:
SELECT m[1] AS word FROM t, regexp_matches(t.word, '([a-zA-Z]+(?:-[a-zA-Z]+)*)', 'g') AS m WHERE m[1] NOT IN ('and', 'et', 'und');
规则说明:
- 正则
([a-zA-Z]+(?:-[a-zA-Z]+)*)只会匹配由字母组成、允许中间包含连字符-的合法单词,自动跳过逗号、空白、其他特殊字符 - 标志
g表示全局匹配,提取所有符合条件的片段 - 最后通过
WHERE条件直接排除指定停用词,符合PostgreSQL语法,执行效率更高
提示:如果需要不区分大小写过滤停用词(比如匹配AND、Et这类变体),可以把过滤条件改成
lower(m[1]) NOT IN ('and', 'et', 'und')
方案2:基于原有regexp_split_to_array写法改造
如果你坚持用拆分的方式,需要先按所有非法字符拆分,再过滤空值和停用词,语句如下:
SELECT word FROM t, unnest(regexp_split_to_array(t.word, E'[^a-zA-Z-]+')) AS word WHERE word <> '' AND word NOT IN ('and', 'et', 'und');
规则说明:
- 拆分正则
[^a-zA-Z-]+表示按所有「不是字母也不是连字符」的连续字符拆分,自动把逗号、空白、其他特殊字符都作为分隔符 - 拆分后会产生空字符串,所以需要加
word <> ''过滤 - 最后同样用IN条件排除停用词,比正则断言写法兼容性和可读性更好
原有写法无法生效的原因
- PostgreSQL的POSIX正则对零宽断言支持有限,你之前用的否定前置断言写法兼容性差,用普通的IN过滤停用词更稳定
- 拆分规则只写
\s+的话无法处理逗号等其他非法字符,导致拆分结果里会保留逗号 - 匹配单词的规则写法不符合PostgreSQL正则语法,所以无法生效
内容的提问来源于stack exchange,提问作者César Castro Aroche
相关产品推荐
相关产品推荐

