我有史以来第一次使用Nginx,基本上不了解它。
我需要在100+网址中将“_”替换为“ - ”。我认为必须有一个简单的方法来使用Nginx,但在Google上找不到任何东西。
谢谢!
编辑:
答案 0 :(得分:13)
不,没有 easy 方法可以做到这一点,但重写引擎仍然可以强制执行,假设您可以对需要转换的破折号数量设置合理的上限单个网址(或者即使您没有,请参阅答案的结尾。)
我是这样做的(测试代码):
rewrite ^([^_]*)_([^_]*)_([^_]*)_([^_]*)_([^_]*)_([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4-$5-$6-$7-$8-$9;
rewrite ^([^_]*)_([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4-$5;
rewrite ^([^_]*)_([^_]*)_(.*)$ $1-$2-$3;
rewrite ^([^_]*)_(.*)$ $1-$2;
这四个重写分别将url中的前8个,4个,2个和1个下划线转换为破折号。每条规则中的下划线数量有意减少2的幂。此块是最有效的规则集,它将在单个URL中从0到15次下划线转换,使用匹配或不匹配每个单独规则的所有16种组合。
您还会注意到,除了最后一个组之外,我在每个规则中都使用了[^_]*
。这避免了在不匹配的情况下使正则表达式引擎执行不需要的回溯。基本上,在正则表达式中有九个通用星.*
导致O(n 9 )复杂度(这是非常糟糕的)在“最坏情况”中,这是一个非匹配,实际上是你最常见的情况。 (对于那些希望真正理解底层库实际执行regexp的人,我可以推荐this book。)
出于这个原因,如果你可以对破折号的数量设置一个小于15的限制,我建议删除第一个规则,或者前两个规则。仅最后三条规则将最多转换为7个下划线;最后两个将最多转换为3。
最后,您没有提及将用户重定向到新网址。 (而不是仅仅在强调的网址和正确的网址上提供内容,这通常是搜索引擎坚果所不喜欢的。仅供参考。)如果这就是你所需要的,你将不得不将这些重写放入一个特殊的地方。在网址中存在下划线时触发的位置,并在四次重写结束时将用户重定向到新网址:
location ~ _ {
rewrite ^([^_]*)_([^_]*)_([^_]*)_([^_]*)_([^_]*)_([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4-$5-$6-$7-$8-$9;
rewrite ^([^_]*)_([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4-$5;
rewrite ^([^_]*)_([^_]*)_(.*)$ $1-$2-$3;
rewrite ^([^_]*)_(.*)$ $1-$2;
rewrite ^ $uri permanent;
}
这还增加了在单个网址中翻译无限数量下划线的好处,但代价是更多的下划线重定向到用户的浏览器。
HTH ;-P
答案 1 :(得分:2)
这已经过时了,但我必须指明上面的答案需要更正为使用 n 不同数量的重新编号 n 是URL中存在的下划线数量是完全不必要的。使用3种不同的位置指令和重写规则可以解决这个问题,同时在常规表达中结合以下场景:
网址的MIDDLE中有一个或多个underocres
location ~*^/(?<t1>\_+)(?<t2>[a-zA-Z0-9\-]*)$ {
return 301 $scheme://$host/-$t2;
}
location ~*^/(?<t2>[a-zA-Z\_0-9\-]*)(?<t1>\_+)$ {
return 301 $scheme://$host/$t2-;
}
location ~*^/(?<t2>[a-zA-Z0-9\-]*)(?<t1>\_+)(?<t3>[a-zA-Z0-9\-]*)$ {
return 301 $scheme://$host/$t2-$t3;
}
这三个指令会递归地用' - '替换所有下划线,直到没有留下
-BeWilled