2

我的正则表达式应该匹配任何序列a, b, c, or d, 或字符x; 该字符串"abcdxabcd"应具有三个单独的匹配项"abcd""x""abcd"

我不明白以下正则表达式之间的区别,我正在寻找括号如何影响结果的详细解释。对于测试字符串"abcdxabcd"

  1. /[abcd]+|x/这个似乎有效。后面四个没有。
  2. /(d|[abc])+|x/返回三个匹配组 {d}、{[empty]} 和 {d}
  3. /(d|[abc]+)+|x/返回三个匹配组 {d}、{[empty]} 和 {d}
  4. /(d|[abc]+)+|(x)/返回三个匹配组 {d, [empty]}、{[empty],x} 和 {d,[empty]}
  5. /((d|[abc]+)+|(x))/返回三个匹配组 {abcd, d, [empty]}, {x,[empty],x} 和 {abcd, d, [empty]}

我对匹配组的概念并不十分熟悉,这是我的问题的一部分。我在这里的目标不是找到一个有效的表达方式,而是理解这些案例之间的差异并了解那些不起作用的表达方式实际上在做什么。

4

1 回答 1

0

=========/[abcd]+|x/

这绝对有效,此表达式匹配[abcd]+OR|匹配 a x。匹配字母、和的[abcd]+一个或多个组合。匹配文字.abcdxx

因此,当您运行它时abcdxabcd[abcd]+首先匹配abcd,然后x匹配该文字,x然后[abcd]+匹配第二个abcd

现在您完全正确,这些是单独的匹配项,换句话说,如果您要/^[abcd]+|x$/用作正则表达式(注意锚点^$,您会注意到这不会匹配abcdxabcd

=========/(d|[abc])+|x/

这是完全不同的表达方式。(d|[abc])+匹配 a dor[abc]并捕获捕获组编号 1 内的任何匹配项,但此表达式重复一次或多次,因为+捕获组包含与其中的内容匹配的最后一个内容。

因此,当您对 , 运行此abcdxabcd操作时,then也a匹配,但 then匹配,这是整个组匹配的最后一件事,因此该组匹配的值也是匹配组 1,即.[abc]bcdd(d|[abc])+dd

现在x是匹配的,x并且该组没有捕获任何东西,所以第二个捕获组是一个空的。

现在最后一个捕获组的工作方式与第一个相同,所以我们得到{d}{}{d}

我可以继续一一解释其余的表达方式,但这需要大量打字。我希望你能看到这对其他人是如何工作的。

总结:当一个组不匹配时,它会捕获空字符串(我不知道这是否真的发生在 Ruby 代码中,或者它只是为清楚起见由 Rubular 显示)。某个组捕获的最后一件事是保留的内容,如果该组匹配多次,则先前的捕获将消失。

编辑:捕获组只是捕获或记住其中匹配的表达式,因此您可以通过反向引用在正则表达式本身中引用它,或者在替换字符串中引用它。

啊哈我忘了告诉你捕获组从1开始编号,从左到右计数。

让我给你看一个例子:如果你想匹配一个紧随其后重复的字符,你可以使用:

(.)\1

.匹配单个字符,捕获组 1中()匹配的内容,然后我们尝试匹配组 1 匹配的相同内容,使用\1称为反向引用。

另一个例子:假设您想再匹配一个由破折号分隔的字符,如下所示:abc-53并且您想在替换字符串中引用它们。

你会匹配:

([^-]+)-([^-]+)

([^-]+)匹配一个或多个不是破折号的字符-,现在我们使用在替换字符串中捕获的内容,如下所示:

$2 == $1

这将导致转换abc-5353 == abc.

捕获组和其他正则表达式功能的主题可能需要大量解释,您可以查看regular-expressions.info了解更多信息。

于 2013-10-02T16:38:57.880 回答