Regex 为什么不是';ModRewrite是否按预期返回正则表达式?

Regex 为什么不是';ModRewrite是否按预期返回正则表达式?,regex,mod-rewrite,Regex,Mod Rewrite,我正在为我的网站开发动态子域,到目前为止,我提出的重写代码是: RewriteRule ^.+\:\/\/?([a-zA-Z0-9]+)\.{1}.+\.{1}.+\/?([a-zA-Z0-9]*)?\/?([a-zA-Z0-9]*)?\/?([a-zA-Z0-9]*)?$ /app.php?var1='$1'&var2='$2'&var3='$3'&var4='$4' 当我在正则表达式测试仪中测试它时,我得到的是 我的模拟输入是:http://testuser.te

我正在为我的网站开发动态子域,到目前为止,我提出的重写代码是:

RewriteRule ^.+\:\/\/?([a-zA-Z0-9]+)\.{1}.+\.{1}.+\/?([a-zA-Z0-9]*)?\/?([a-zA-Z0-9]*)?\/?([a-zA-Z0-9]*)?$ /app.php?var1='$1'&var2='$2'&var3='$3'&var4='$4' 
当我在正则表达式测试仪中测试它时,我得到的是

我的模拟输入是:
http://testuser.testdomain.com/test/this/out

我的回报是:
app.php?var1='testuser'&var2='&var3='&var4='

我期待的是:
app.php?var1='testuser'&var2='test'&var3='this'&var4='out'

你可以在这里看到我的工作:

编辑:

我不太理解第二种情况,到目前为止我有:

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^([a-zA-Z0-9]+)?/?([a-zA-Z0-9]+)?/?([a-zA-Z0-9]+)?/?([a-zA-Z0-9]+)?$ app.php?content=$1&id=$2&selector=$3&action=$4
RewriteRule ^([a-zA-Z0-9]+)?/?([a-zA-Z0-9]+)?/?([a-zA-Z0-9]+)?/?([a-zA-Z0-9]+)?/?$ app.php?content=$1&id=$2&selector&$3&action=$4

RewriteCond %{REQUEST_URI} !-d

RewriteRule ^(.+://{1}){1}([a-zA-Z0-9]+).{1}([a-zA-Z0-9]+.{1}[a-zA-Z0-9]+/){1}([a-zA-Z0-9]*)?/?([a-zA-Z0-9]*)?/?([a-zA-Z0-9]*)?/?([a-zA-Z0-9]*)?$ $1$3app.php?&content=$4&id=$5&selector=$6&action=$7
第一个条件是未设置当前正在工作的子目录。
我仍在处理的第二个条件是,我不知道如何使用RewriteCond,也找不到很好地解释它的文档。

您试图在
RewriteRule
中匹配太多内容,它本身只接收路径
test/this/out
,而不接收协议或主机。要从主机捕获子域,必须首先将
%{HTTP_host}
RewriteCond
匹配到
%1
变量中,然后匹配
RewriteRule
中的路径段

注意,我使用表达式
(:?([^.]+)\)?
仅捕获点之前的部分作为子域。外部零件上的
(:?)
确保点本身不会在
%1
中被捕获

作为一条规则进行更新和重写: 经过一些实验,我找到了如何在一个非常复杂的表达式中实现这一点。它使用相同的
RewriteCond
匹配模式将子域抓取到
%1
,但将路径段替换为
(?:([^/]+)(?:/|$)?

具体如下:

  • ^
    重写规则接收的字符串的开头(路径)
  • (?:
    不要为整个结构捕获变量
  • ([^/]+)
    捕获下一个
    /
    之前的所有内容(但不包括它)
  • (?:
    不要捕捉接下来会发生什么
  • /|$
    …可以是斜杠或字符串的结尾
    $
  • 关闭该斜杠或结束匹配组
  • 关闭整个结构的外部组
  • 并使整个事情成为可选的
上面的全部内容将匹配第一个路径段(
test
在您的示例中
/test/this/out
)。然后再重复两次以捕获其他两个变量

加上
RewriteCond
条件和子域匹配,它看起来像

RewriteCond %{REQUEST_FILENAME} !-d
# Added condition for negative match on existing files
RewriteCond %{REQUEST_FILENAME} !-f
# Case-insensitive host match captures the subdomain into %1
# Using [^.]+ to match everything up to the first dot
# using a non-capturing outer group so the dot isn't grabbed
RewriteCond %{HTTP_HOST} ^(?:([^.]+)\.)?test\.com [NC]
# Match each segment optionally into $1,$2,$3
RewriteRule ^(?:([^/]+)(?:/|$))?(?:([^/]+)(?:/|$))?(?:([^/]+)(?:/|$))? index.php?subdomain='%1'&var2='$1'&var3='$2'&var4='$3' [L]
如果您可能需要附加其他查询字符串参数,请在每个参数的末尾添加
[QSA]
标志,如
[L,QSA]
所示


您试图在
重写规则
中匹配太多内容,该规则本身只接收路径
测试/this/out
,而不接收协议或主机。要从主机捕获子域,必须首先将
%{HTTP_host}
RewriteCond
匹配到
%1
变量中,然后匹配
RewriteRule
中的路径段

注意,我使用表达式
(:?([^.]+)\)?
仅捕获点之前的部分作为子域。外部零件上的
(:?)
确保点本身不会在
%1
中被捕获

作为一条规则进行更新和重写: 经过一些实验,我找到了如何在一个非常复杂的表达式中实现这一点。它使用相同的
RewriteCond
匹配模式将子域抓取到
%1
,但将路径段替换为
(?:([^/]+)(?:/|$)?

具体如下:

  • ^
    重写规则接收的字符串的开头(路径)
  • (?:
    不要为整个结构捕获变量
  • ([^/]+)
    捕获下一个
    /
    之前的所有内容(但不包括它)
  • (?:
    不要捕捉接下来会发生什么
  • /|$
    …可以是斜杠或字符串的结尾
    $
  • 关闭该斜杠或结束匹配组
  • 关闭整个结构的外部组
  • 并使整个事情成为可选的
上面的全部内容将匹配第一个路径段(
test
在您的示例中
/test/this/out
)。然后再重复两次以捕获其他两个变量

加上
RewriteCond
条件和子域匹配,它看起来像

RewriteCond %{REQUEST_FILENAME} !-d
# Added condition for negative match on existing files
RewriteCond %{REQUEST_FILENAME} !-f
# Case-insensitive host match captures the subdomain into %1
# Using [^.]+ to match everything up to the first dot
# using a non-capturing outer group so the dot isn't grabbed
RewriteCond %{HTTP_HOST} ^(?:([^.]+)\.)?test\.com [NC]
# Match each segment optionally into $1,$2,$3
RewriteRule ^(?:([^/]+)(?:/|$))?(?:([^/]+)(?:/|$))?(?:([^/]+)(?:/|$))? index.php?subdomain='%1'&var2='$1'&var3='$2'&var4='$3' [L]
如果您可能需要附加其他查询字符串参数,请在每个参数的末尾添加
[QSA]
标志,如
[L,QSA]
所示


您是否打算让这3条路径段都是可选的?令人惊讶的是。。我刚刚解决了我自己的问题。我将匹配任何字符串的前两个“.”字符更改为“[a-zA-Z0-9]”模式,以某种方式解决了问题。不知道怎么说,也许有人对此有解释?将来可能会帮助别人。新代码是
RewriteRule^.+\:\/\/?([a-zA-Z0-9]+)\.{1}[a-zA-Z0-9]+\.{1}[a-zA-Z0-9]+\/?([a-zA-Z0-9]*)?\/?([a-zA-Z0-9]*)?$app.php?var1='testuser'&var2='test'&var3='this'&var4='out'如果它现在能工作,可能是一个过度匹配的代码。协议https?域将永远不会出现在重写规则中。您确定已将
testuser
成功匹配到var1中吗?仅在regex编辑器中。。所以我刚才写的这条规则基本上是行不通的?不,这条规则不行。你需要额外的重写。那么,您希望这3个路径变量是可选的还是必需的