Apache RewriteCond 匹配 www 和非 www

Apache RewriteCond match both www and non-www

我正在尝试根据域名将对 sitemap.xml 的请求重定向到不同的站点地图文件,例如 mydomain.sitemap.xmlanotherdomain.sitemap.xml 等...

到目前为止我有这个,但它只适用于非 www 域:

RewriteCond %{HTTP_HOST} ^(?!www\.)([^.]+) [NC]
RewriteRule ^sitemap\.xml$ /%1.sitemap.xml [L,NC]

有什么建议吗?

RewriteCond %{HTTP_HOST} (www\.)?([^.]+) [NC]
RewriteRule ^sitemap\.xml$ /%2.sitemap.xml [L,NC]

将其更改为您想要的效果:

RewriteCond %{HTTP_HOST} ^(?:www\.)?([^.]+)\.
RewriteRule ^sitemap\.xml$ /%1.sitemap.xml [L,NC]

更新

为了解释正则表达式,这里是它的作用:

^(?:www\.)?([^.]+)\.

^ 表示匹配字符串的开头,因此这会将正则表达式锚定到字符串的开头。

(?:) 表示仅将其用于分组,不捕获匹配的内容(因此在这种情况下不会用完 %1)。

www\. 只是表示匹配 "www.",点必须用斜杠转义,否则它有特殊含义。

括号后的问号(?:www\.)?表示该组是可选的,存在或不存在,都匹配成功。

所以此时我们要么仍在字符串的开头,要么就在 "www.".

之后

现在我们继续使用 ([^.]+)\. 将所有内容带到下一个点。这是有效的,因为...

() 是一个捕获组,因此在本例中它捕获与 %1.

匹配的内容

[^.]+ 表示用 [^.] 匹配任何不是点的东西,在这种情况下,点不需要转义,因为它在 "character class" 中。开头的插入符号 ^ 使其成为否定匹配,因此匹配未指定的任何内容。之后的 + 表示匹配其中的一个或多个,然后执行 "greedily" 以便它可以匹配最长的字符串。

因此,由于我们是贪婪匹配,这意味着关闭 \. 实际上不是必需的,因为无论如何贪婪匹配都会到达那里,但我喜欢将锚点放在正则表达式中,因为它使它们更容易阅读和理解。这不会造成任何伤害,因为任何有效的主机名在我们匹配的主机名之后都会有另一部分。

另一种选择是使用 (?:\.|$) 来选择字符串末尾的点 管道是 "alternation" 说 "this or that" (或者那个,或者那个,如果使用更多的话)。非捕获组用于包含交替。所以在那种情况下它会变成:

^(?:www\.)?([^.]+)(?:\.|$)

这意味着它也适用于 "localhost".