使用正则表达式 - 重复模式

时间:2011-10-28 01:26:08

标签: ruby regex regex-group

我正在尝试使用正则表达式来匹配某些文本。

以下模式是我想要收集的内容。

@Identifier('VariableA', 'VariableB', 'VariableX', ..., 'VariableZ')

我想获取动态数量的变量,而不是固定的两个或三个变量。 有没有办法做到这一点?我有一个现有的正则表达式:

\@(\w+)\W+(\w+)\W+(\w+)\W+(\w+)

这会捕获标识符和最多三个变量。

编辑:这只是我,还是正则表达不像我正在制作的那样强大?

4 个答案:

答案 0 :(得分:3)

您希望scan用于此类事情。基本模式是:

s.scan(/\w+/)

这会给你一个包含单词字符的所有连续序列的数组:

>> "@Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ')".scan(/\w+/)
=> ["Identifier", "VariableA", "VariableB", "VariableX", "VariableZ"]

你说你可能有多个你的模式实例,周围有任意的东西。您可以使用嵌套的scan s来处理它:

s.scan(/@(\w+)\(([^)]+?)\)/).map { |m| [ m.first, m.last.scan(/\w+/) ] }

这将为您提供一个数组数组,每个内部数组将“Identifier”部分作为第一个元素,而“Variable”部分作为第二个元素中的数组。例如:

>> s = "pancakes @Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ') pancakes @Pancakes('one','two','three') eggs"
>> s.scan(/@(\w+)\(([^)]+?)\)/).map { |m| [ m.first, m.last.scan(/\w+/) ] }
=> [["Identifier", ["VariableA", "VariableB", "VariableX", "VariableZ"]], ["Pancakes", ["one", "two", "three"]]]

如果您可能在“变量”位中面对转义引号,那么您将需要更复杂的内容。


关于表达的一些注释:

@            # A literal "@".
(            # Open a group
  \w+        # One more more ("+") word characters ("\w").
)            # Close the group.
\(           # A literal "(", parentheses are used for group so we escape it.
(            # Open a group.
  [          # Open a character class.
    ^)       # The "^" at the beginning of a [] means "not", the ")" isn't escaped because it doesn't have any special meaning inside a character class.
  ]          # Close a character class.
  +?         # One more of the preceding pattern but don't be greedy.
)            # Close the group.
\)           # A literal ")".

这里你真的不需要[^)]+?,只是[^)]+会这样做,但我习惯使用非贪婪的形式,因为这通常就是我的意思。分组用于分隔@IdentifierVariable部分,以便我们可以轻松获得所需的嵌套数组输出。

答案 1 :(得分:0)

但亚历克斯认为你的意思是你想要四次抓住同样的东西。如果你想捕捉相同的模式,但不同的东西,那么你可能想要考虑两件事:

迭代。在perl中,你可以说

while ($variable =~ /regex/g) {

'g'代表'global',意味着每次调用正则表达式时,它都匹配/ next / instance。

另一个选项是递归。写这样的正则表达式:

/(what you want)(.*)/

然后,你有一个包含第一个东西的反向引用1,你可以将它推到一个数组,然后你会反复引用它,直到它不再匹配为止。

答案 2 :(得分:0)

您可以简单地使用(\w+)

给定输入字符串 @Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ')

结果将是:

  1. Identifier
  2. VariableA
  3. VariableB
  4. VariableX
  5. VariableZ
  6. 这适用于任意数量的变量。

    为了将来参考,在Rubular上使用正则表达式的想法很简单有趣。

答案 3 :(得分:0)

所以你问是否有办法捕获标识符和任意数量的变量。我担心你只能用支持捕获的正则表达式引擎来做到这一点。请注意,捕获捕获组不是同一回事。你想要记住所有的“变量”。使用简单的捕获组无法做到这一点。

我不知道Ruby是否支持这个,但我确信.NET和新的PERL 6支持它。

在您的情况下,您可以使用两个正则表达式。一个用于捕获标识符,例如^\s*@(\w+)

和另一个捕获所有变量,例如result = subject.scan(/'[^']+'/)