Mod Rewrite Regex - 多个负前瞻
Posted
技术标签:
【中文标题】Mod Rewrite Regex - 多个负前瞻【英文标题】:Mod Rewrite Regex - Multiple Negative Lookaheads 【发布时间】:2011-10-07 07:41:46 【问题描述】:我目前有正在工作的 Mod Rewrite Regex:
RewriteEngine On
RewriteCond %QUERY_STRING ^(.*)$
RewriteRule ^(.*/)?((?:cmd)[^/]*)/((?!(?:cmd)[.+]*)(.+)) $1?$2=$3&%1 [L]
该正则表达式采用以下 URL 并将其转换为紧随其后的 URL:
www.site.com/cmd1/param/cmd2/param2/stillparam2
转成www.site.com/index.php?cmd1=param&cmd2=param2/stillparam2
这很好用,但我还想创建另一个否定的前瞻断言,以确保 URL 块 - 即 /texthere/
参数 - 不包含下划线。无效字符串可能如下所示:www.test.com/cmd/thing/getparam_valuehere
;正则表达式应将cmd/thing
解析为键值对并忽略字符串的其余部分。然后,我还将编写另一个 RewriteRule 以将带有下划线的 URL 块添加为另一个 URL 参数。将发生以下 URL 转换:
www.test.com/cmd/param1/cmd2/directory/param2/sortorder_5
www.test.com?cmd=param1&cmd2=directory/param2&sortorder=5
如果我还不够清楚,请告诉我。任何帮助都会很棒。
注意:我已经尝试使用嵌套在已经存在的一个负前瞻 - (?!(?!))
- 并尝试在两个负前瞻上使用 |
,但两种解决方案都不起作用。我认为也许还有其他更根本的错误?
谢谢大家。
编辑:我还尝试了以下方法 - 我真的认为它会起作用(但显然,没有!)
RewriteRule ^(.*/)?((?:cmd)[^/]*)/((?!(?:cmd)[.+]*)(?![.+]*(?:_)[.+]*)(.+)) $1?$2=$3&%1 [L]
执行以下操作:
www.test.com/cmd/param1/sortorder_1/
转换为
www.test.com?cmd=param1/sortorder_1/
什么时候应该改为:www.test.com?cmd=param1&sortorder=2/
。将/sortorder_2/
转换为&sortorder=2
的规则尚未创建,但希望您能明白我的意思)。
【问题讨论】:
Lookbehinds 必须是固定长度,可变长度的lookaheads 应该没问题。 是的,这里肯定只使用了负前瞻。感谢您的回复! 我还尝试了以下方法:RewriteRule ^(.*/)?((?:cmd)[^/]*)/((?!(?:[A-Za-z0-9])*_+(?:[A-Za-z0-9])*)(.+)) $1?$2=$3&%1 [L]
。在这里,我删除了原来的(工作的)否定前瞻,并将其替换为另一个应该确保 URL 块中不存在下划线的前瞻,然后再将其作为参数的一部分。这不起作用,并生成了以下查询字符串:cmd=key/to/command/value_here/sortorder_5/
我打算让它停在/value_here/
以便我可以验证负前瞻是否正确找到了下划线段。没有运气。
【参考方案1】:
经过大约四天的试验,我最终找到了一个与我最初预期的有所不同的解决方案。我只是将所有实际的 URL 操作删除到我的 index.php 文件中,并通过那里路由所有请求。这是我的(更干净的).htaccess 文件:
Options +FollowSymlinks
RewriteEngine On
RewriteCond %QUERY_STRING (.*)
RewriteRule (.*) index.php?path=$1 [QSA,L]
这是我用来解析输入的 URL 的代码块:
preg_match_all('|/([A-Za-z0-9]+)((?!/)[A-Za-z0-9-.]*)|', $ _GET['path'], $matches);
// Remove all '$_GET' parameters from the actual $_GET superglobal:
foreach($matches[0] as $k => $v)
$search = '/' . substr($v, 1);
$_GET['path'] = str_replace($search, '', $_GET['path'], $count);
// Add $_GET params to URL args
for ($i = 0; $i < count($matches[1]); $i++)
self::$get_arguments[$matches[1][$i]] = $matches[2][$i];
// Retrieve all 'cmd' properties from the URL and create an array with them:
preg_match_all('~(cmd[0-9]*)/(.+?)(?=(?:cmd)|(?:\z))~', $_GET['path'], $matches);
if (isset($matches[1][0]))
return self::$url_arguments = array_combine($matches[1], $matches[2]);
在这样的网址上:
http://localhost/frame_with_cms/frame/www/cmd/one/cmd2/two/cmd3/three/cmd4/four/getparam_valuepart1_valuepart2/cmd5/five/
它成功生成了这些单独的数组,然后我用它们来处理请求:
Array
(
[getparam] => valuepart1_valuepart2
)
Array
(
[cmd] => one/
[cmd2] => two/
[cmd3] => three/
[cmd4] => four/
[cmd5] => five/
)
感谢所有花时间阅读和回复的人。
【讨论】:
我不得不承认我的第一个想法是,为什么要在 .htaccess 文件中这样做。但是,考虑到限制,此回复并不能真正解决您的问题。【参考方案2】:保留您的工作规则并在当前规则之前将 param_value 重写为查询字符串不是更容易吗?
类似
RewriteRule ^(.*)?/([^_/]+)_([^/]+)/ $1/?$2=$3 [N,QSA]
应将所有 /param_value/ 部分作为 param=value 附加到查询字符串中。
小心使用 N 标志,你可能会陷入无限循环。
【讨论】:
我会在下班后尝试并发布结果。感谢您的回复! @CharString我在第一个之前包含了上面的重写规则,我得到了一个无限循环!还是谢谢你的回复,非常感谢。以上是关于Mod Rewrite Regex - 多个负前瞻的主要内容,如果未能解决你的问题,请参考以下文章