不,没有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 的递减幂。该块是最有效的规则集,它将使用匹配或不匹配每个单独规则的所有 16 种组合,将单个 url 中出现的 0 到 15 次下划线进行转换。
You will also notice that I used [^_]*
on every group except the last one, in every rule. This avoids having the regexp engine perform unneeded backtracking in the case of non matches. Basically, having nine universal stars .*
in a regexp causes O(n9) complexity (which is quite bad) in the "worst case", which is a non match, which would actually be your most frequent case. (I can recommend this book http://regex.info/book.html for those who wish to really understand how a regexp is actually executed by the underlying library.)
因此,如果您可以对破折号的数量设置小于 15 的限制,我建议取消第一条规则或前两条规则。仅最后三个规则就可以翻译最多 7 个下划线;最后两个将翻译为 3。
最后,您没有提到将用户重定向到新网址。 (而不是只在带下划线的网址和正确的网址上提供内容,这通常会受到搜索引擎迷的皱眉。仅供参考。)如果这就是您所需要的,您将必须将这些重写放入一个特殊的location 在 url 中存在下划线时触发,并在四次重写结束时将用户重定向到新的 url:
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;
}
这还增加了在单个 URL 中翻译无限数量的下划线的好处,但代价是不止一个重定向到用户的浏览器。
HTH ;-P