Php 解析前后没有特定字符的参数模式

Php 解析前后没有特定字符的参数模式,php,regex,Php,Regex,为了练习,我正在创建自己的PHP路由器。此路由器可以接受如下指定的参数: {i:variableName} i代表参数类型(在本例中为整数),而variableName代表variableName 单个路由URI可能如下所示: /home/{i:id}-{s:noVar}/{m:varName}/{s:someOther} 为此,我创建了以下正则表达式模式: [^{}]*({((?<type>\D):)?(?<name>[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]+

为了练习,我正在创建自己的PHP路由器。此路由器可以接受如下指定的参数:

{i:variableName}

i
代表参数类型(在本例中为整数),而
variableName
代表variableName

单个路由URI可能如下所示:

/home/{i:id}-{s:noVar}/{m:varName}/{s:someOther}

为此,我创建了以下正则表达式模式:

[^{}]*({((?<type>\D):)?(?<name>[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]+)})[^{}]*
这方面的一个例子是,我将无法做以下事情:

/home/{i:id}{s:noVar}/{m:varName}{s:someOther}

它们之间需要有字符

我认为这段正则表达式可以做到,“不要包含零个或多个
{
}
字符

当我在像
/home/{I:id}{s:noVar}/{m:varName}/{s:someOther}
这样的模式上运行这个正则表达式时,它仍然检索所有参数,甚至是相邻的参数


这是怎么可能的?我如何使正则表达式只检索彼此不相邻的参数?

我建议匹配2个或更多连续的
{…}
块并忽略这些匹配,而只处理所有其他
{…}
(非相邻)块。使用众所周知的PCRE:

(?:{(?[a-zA-Z]:)?[a-zA-Z]\w*}{2,}(*SKIP)(*F){(?:(?[a-zA-Z]):)(?[a-zA-Z]\w*}

说明

  • (?:{(?[a-zA-Z]:)?[a-zA-Z_uw*}{2,}(*SKIP)(*F)
    -正则表达式中与下面解释的模式(仅不包括捕获组)匹配的第一个可选分支,该模式连续出现,请参见
    {2,
    ,这意味着在一段时间内匹配两个或多个实例。
    (*SKIP)(*FAIL)
    谓词使正则表达式引擎忽略此匹配并继续
  • |
    -或符合我们的需要:
  • {
    -打开的
    {
  • (?:(?[a-zA-Z]):)?
    -与ASCII字母(捕获到组“type”)和
    匹配的可选组
  • (?[a-zA-Z]\w*)
    -将“名称”分组以捕获ASCII字母或
    (请参见
    [a-zA-Z]
    ,后跟0+字字符(来自
    [a-zA-Z0-9\
    范围)
  • }
    -关闭
    }

(?和
(?!{)括起您的第一个图案
.See@WiktorStribiżew你是什么意思?我还是正则表达式的初学者。你知道
-ÿ
创建了一个范围吗?这是你的意图吗?@WiktorStribiżew这是一个变量名,我基本上是在谷歌上搜索的。我猜这已经脱离主题了,但它到底做了什么?我不明白一点:
I:
really可选?检查是否对您有效。这只是变得更复杂了,感谢您的解释。一旦您了解了模式匹配的内容,就不难了。起初,有
(?和
(?!{)
,它们现在在哪里?您在完整正则表达式开头编写的内容是否相同?请阅读我在答案中的解释。我们匹配连续的
{}
块,然后丢弃它们。只有匹配的块是独立的块。如果我们使用lookback
(?)和lookahead
(?!{)
我们还将排除
{}
块前面紧跟
}
或后面紧跟
{
。并且没有保证那里有一个完整的块。我们可以在一个块之后检查一个块,但是我们不能在一个块之前检查一个块。当然,如果您确定块的周围将只有
{}
,您可以使用环视方法。
[^{}]*
(?:{(?:[a-zA-Z]:)?[a-zA-Z_]\w*}){2,}(*SKIP)(*F)|{(?:(?<type>[a-zA-Z]):)?(?<name>[a-zA-Z_]\w*)}