1

简化代码:

SELECT 'ok' WHERE '/articles/new/' ~ '^/articles/(?!new)([\w-]+)/$';

示例,我想要什么:

'/articles/new/' => ''
'/articles/new-york/' => 'ok'
'/articles/other-string/' => 'ok'

而且,有什么问题:

'/articles/new/' => ''
'/articles/new-york/' => '' /* Wrong */
'/articles/other-string/' => 'ok'

那么,我怎样才能只阻止这个词呢?

优化

在 PostgreSQL 数据库中,我有一个表 ( page),它有列path, title, file, regex_path etc.

列中的值path如下所示:

/
/articles/
/articles/:category-code/
/articles/:category-code/:article-code/
/articles/:category-code/:article-code/edit/
/articles/new/
/members/
/members/:username/

:表示它是一个参数(PHP 根据 regex_path 获取名称和内容——第一个版本)

从外部(PHP)数据库获取一个值(URL)。例子:

/ /* Main page */
/articles/ /* List all article */
/articles/it/ /* List articles in IT category */
/articles/it/ipad-mini-2/  /* Article */
/articles/it/ipad-mini-2/edit/ /* Edit article */
/articles/new/ /* New article */
/members/ /* Member list */
/members/someone/ /* Member datasheet */

如何选择正确的行,其中值(URL)与路径匹配(最快的方式,没有正则表达式)?

例子

在: /articles/it/ipad-mini-2/

出:行,其中path是:/articles/:category-code/:article-code/

4

2 回答 2

3

这更快:

SELECT *
FROM   tbl 
WHERE  txt LIKE '/articles/%'
AND    txt <>   '/articles/new/';  -- only exclude this exact string

以“/articles/”开头的所有内容,但不包括“/articles/new/”

或者,排除整个分支:

...
AND    txt NOT LIKE  '/articles/new/%';

要么包括 '/articles/new-york/',因为在这里,'new' 不是紧跟在 '/' 之后。

性能测试

正则表达式通常LIKEor =or更昂贵<>
用 测试EXPLAIN ANALYZE。或者EXPLAIN (ANALYZE, TIMING OFF)抑制噪音。看:

我进行了测试以确认我的主张。它比正则表达式快 10 - 20 倍。

'^/articles(?!/new/)/([\w-]+)/$' -- Daniel's solution

..应该简化为(快一点):

'^/articles/(?!new/)[\w-]+/$'

db<>fiddle here
sqlfiddle

第二个正则表达式的解释:

^... 字符串开头
/articles/... 文字匹配
(?!new/)...否定前瞻匹配,其中没有字符串 'new/' 跟随
[\w-]... 括号表达式包含类速记 \w加上破折号-
+... 1 次或更多次
/... 文字匹配
$。 .. 字符串结束

于 2013-07-10T14:36:22.720 回答
1

你很接近,我改变了否定的前瞻性,更具体。仅当前瞻找到 时才匹配失败/new/

^/articles(?!/new/)/([\w-]+)/$

结果

/articles/new
/articles/new/
/articles/new-york/ => OK
/articles/other-string/ => OK
/articles/notnew/ => OK

测试在这里:

雷伊

于 2013-07-10T14:22:06.127 回答