我能够将URL字符串的一部分与指定的格式匹配。这看起来像这样:
/foo/firstName[firstId]/optional1[oId1]/optional2[oId2]/…
其中name [id]需要在一起(不仅仅是name或[id]),但只有firstName [firstId]是必需的,最多可以有六个可选条目。
我目前将此条目与
匹配/(?:([^\[]+)\[([^\]]+)\])/
可以单独使用,因为您可以看到in this example但不能使用完整的网址(example)。在第二个版本中,中间匹配被覆盖,只有最后一个匹配。
我该如何解决这个问题?
修改
因为我不知道亲爱的读者是否理解我的问题,所以我创建了一个简化版本。
鉴于字符串:
/foo/x/y/z
/foo/x/y
/foo/x
我现在想要匹配所有这三个并取回x,y和z。
我可以用
^\/foo(?:\/(\w))+
匹配整个字符串。但我只得到z(或只有y或只有x)。我该如何改变?
答案 0 :(得分:1)
在example中,您只需指定所需的出现次数
^\/foo\/(?:([^\[]+)\[([^\]]+)\]){1,7}$
因此,我们将{1,7}
表示最小值为1(第一个必需参数name
)和6个可选项。见regex101 test
超越,如果你想与网址匹配,我认为我们可以改善一点,包括:
^(?:(?:(?:http\:\/\/)?(?:www\.)?)[^\/]*){0,1}\/foo\/(?:([^\[]+)\[([^\]]+)\])+
会将您的规则放入真实网址,例如: www.stackoverflow.com/foo/firstName[firstId]/optional1[oId1]/optional2[oId2]/
修改强>
如果你想要所有参数,那么它会有点手动:
^(?:(?:(?:http\:\/\/)?(?:www\.)?)[^\/]*){0,1}(?#parameter1)\/(foo)(?#parameter2)(?:\/([^\/]*\[[^\/]*\]))(?#optional1)(?:\/([^\/]*\[[^\/]*\]))?(?#optinal2)(?:\/([^\/]*\[[^\/]*\]))?(?#optional3)(?:\/([^\/]*\[[^\/]*\]))?(?#optional4)(?:\/([^\/]*\[[^\/]*\]))?(?#optional5)(?:\/([^\/]*\[[^\/]*\]))?(?#optional6)(?:\/([^\/]*\[[^\/]*\])\/?)?$
无法确定未确定数量的群组capturing-a-pattern-of-unknown-repitition-in-pcre
答案 1 :(得分:0)
Ruud的评论似乎是门票: http://regex101.com/r/zQ0uO3
它不会消除最初的http文件夹“/ foo”,但你可以通过javascript制作一个小mod和/或解析它。它看起来是一个非常好的解决方案。
答案 2 :(得分:0)
中间匹配被覆盖,只有最后一个匹配。
捕获组可能会多次匹配,但它只有一个结果(在JavaScript中) - 您正在访问最后一个匹配项。只有不同的正则表达式引擎才允许访问中间匹配。另请参阅http://www.regular-expressions.info/captureall.html。
如何更改?
除了添加更多显式捕获组之外,您无法修改正则表达式以提供多个结果:^\/foo(?:\/(\w))?(?:\/(\w))?(?:\/(\w))?(?:\/(\w))?…
。难看。
最简单的解决方案可能是将所有部分作为一个长字符串,然后通过斜杠将split
作为一个数组:
> str.match(/^\/foo\/(?:[^\[]+\[[^\]]+\])+/gi)[0].split("/").slice(1);
["foo", "firstName[firstId]", "optional1[oId1]", "optional2[oId2]"]
如果表达式更复杂(并且您有多个重复的捕获组),那么您可以对字符串上的单个部分重复exec
正则表达式并在每次迭代中抓取组:
> var regex = /(?:([^\/\[]+)\[([^\]]+)\])/g, match;
> while (match = regex.exec(str)) console.log(match[1], match[2]);
firstName, firstId
optional1, oId1
optional2, oId2