javascript正则表达式:n次可选组

时间:2014-01-14 12:34:11

标签: javascript regex

我能够将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)。我该如何改变?

EXAMPLE

3 个答案:

答案 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)(?:\/([^\/]*\[[^\/]*\])\/?)?$

请参阅regex101 test

无法确定未确定数量的群组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