3

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

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

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

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

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

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

编辑:只是我,还是正则表达式没有我想象的那么强大?

4

4 回答 4

3

你想scan用于这种事情。基本模式是这样的:

s.scan(/\w+/)

这将为您提供一个包含单词字符的所有连续序列的数组:

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

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

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

这将为您提供一个数组数组,每个内部数组将“标识符”部分作为第一个元素,将“变量”部分作为第二个元素中的数组。例如:

>> 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部分,以便我们可以轻松获得所需的嵌套数组输出。

于 2011-10-28T02:25:20.180 回答
0

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

迭代。在 perl 中,你可以说

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

“g”代表“全局”,意味着每次调用正则表达式时,它都会匹配 /next/ 实例。

另一种选择是递归。像这样写你的正则表达式:

/(what you want)(.*)/

然后,你有包含第一件事的反向引用 1,你可以将它推送到一个数组,然后你将递归反向引用 2,直到它不再匹配。

于 2011-10-28T01:41:34.160 回答
0

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

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

结果将是:

  1. Identifier
  2. VariableA
  3. VariableB
  4. VariableX
  5. VariableZ

这适用于任意数量的变量。

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

于 2011-10-28T01:43:07.377 回答
0

所以你问是否有办法同时捕获标识符和任意数量的变量。恐怕您只能使用支持捕获的正则表达式引擎来执行此操作。请注意,捕获捕获组不是一回事。你想记住所有的“变量”。这不能通过简单的捕获组来完成。

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

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

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

于 2011-10-28T02:21:03.940 回答