我正在尝试使用正则表达式来匹配一些文本。
以下模式是我想要收集的。
@Identifier('VariableA', 'VariableB', 'VariableX', ..., 'VariableZ')
我想获取动态数量的变量,而不是固定的两个或三个变量。有没有办法做到这一点?我有一个现有的正则表达式:
\@(\w+)\W+(\w+)\W+(\w+)\W+(\w+)
这将捕获标识符和最多三个变量。
编辑:只是我,还是正则表达式没有我想象的那么强大?
我正在尝试使用正则表达式来匹配一些文本。
以下模式是我想要收集的。
@Identifier('VariableA', 'VariableB', 'VariableX', ..., 'VariableZ')
我想获取动态数量的变量,而不是固定的两个或三个变量。有没有办法做到这一点?我有一个现有的正则表达式:
\@(\w+)\W+(\w+)\W+(\w+)\W+(\w+)
这将捕获标识符和最多三个变量。
编辑:只是我,还是正则表达式没有我想象的那么强大?
你想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 ")".
你在这里并不需要[^)]+?
,只是[^)]+
会这样做,但我习惯使用非贪婪形式,因为这通常是我的意思。分组用于分隔@Identifier
和Variable
部分,以便我们可以轻松获得所需的嵌套数组输出。
但亚历克斯认为你的意思是你想捕捉同样的东西四次。如果你想捕捉相同的模式,但不同的东西,那么你可能需要考虑两件事:
迭代。在 perl 中,你可以说
while ($variable =~ /regex/g) {
“g”代表“全局”,意味着每次调用正则表达式时,它都会匹配 /next/ 实例。
另一种选择是递归。像这样写你的正则表达式:
/(what you want)(.*)/
然后,你有包含第一件事的反向引用 1,你可以将它推送到一个数组,然后你将递归反向引用 2,直到它不再匹配。
您可以简单地使用(\w+)
.
给定输入字符串
@Identifier('VariableA', 'VariableB', 'VariableX', 'VariableZ')
结果将是:
Identifier
VariableA
VariableB
VariableX
VariableZ
这适用于任意数量的变量。
为了将来参考,在Rubular上使用正则表达式的想法既简单又有趣。
所以你问是否有办法同时捕获标识符和任意数量的变量。恐怕您只能使用支持捕获的正则表达式引擎来执行此操作。请注意,捕获和捕获组不是一回事。你想记住所有的“变量”。这不能通过简单的捕获组来完成。
我不知道 Ruby 是否支持这一点,但我确信 .NET 和新的 PERL 6 支持它。
在您的情况下,您可以使用两个正则表达式。一个捕获标识符,例如^\s*@(\w+)
另一个用于捕获所有变量,例如result = subject.scan(/'[^']+'/)