2011-05-20 74 views
3

我想在Ruby中用正则表达式解析模式。该图案是一样的东西,Ruby正则表达式的帮助

<number>? <comma>? <number>? <term>* 

其中:

  • number是一个或多个数字
  • comma","
  • term的形式为[.*][^.*]

和我 我试图捕捉数字和所有条款。为了澄清,这里是有效模式的一些例子:

5,50[foo,bar] 
5,[foo][^apples] 
10,100[baseball][^basketball][^golf] 
,55[coke][pepsi][^drpepper][somethingElse] 

在第一个,我想拍摄550,并[foo,bar] 在第二个,我想拍摄5[foo][^apples]等等。

我想出的模式是:

/(\d+)?,?(\d+)?(\[\^?[^\]]+\])+/ 

但这只是相匹配的数字,最后一项。如果我在最后删除+,那么它只匹配第一项。

回答

1
,我能想到的与最小的努力很可能会被周围组和 +那些已经存在,只是抛出一个额外的捕获组

最简单的解决方案,即

/(\d+)?,?(\d+)?((\[\^?[^\]]+\])+)/ 

此外,你很可能通过只是在做(\d*)代替(\d+)?简化\d表情...

编辑

这里是用来测试上述建议的代码:

matches = [ "5,50[foo,bar]", 
      "5,[foo][^apples]", 
      "10,100[baseball][^basketball][^golf]", 
      ",55[coke][pepsi][^drpepper][somethingElse]" 
      ] 

re = Regexp.new('(\d*),?(\d*)((\[\^?[^\]]+\])+)') 

matches.each do |match| 
    m = re.match(match) 

    puts "\nMatching: #{match}" 
    puts "--------------------" 

    puts "Match 1: #{m[1]}" 
    puts "Match 2: #{m[2]}" 
    puts "Match 3: #{m[3]}" 
end 

和输出:

Matching: 5,50[foo,bar] 
-------------------- 
Match 1: 5 
Match 2: 50 
Match 3: [foo,bar] 

Matching: 5,[foo][^apples] 
-------------------- 
Match 1: 5 
Match 2: 
Match 3: [foo][^apples] 

Matching: 10,100[baseball][^basketball][^golf] 
-------------------- 
Match 1: 10 
Match 2: 100 
Match 3: [baseball][^basketball][^golf] 

Matching: ,55[coke][pepsi][^drpepper][somethingElse] 
-------------------- 
Match 1: 
Match 2: 55 
Match 3: [coke][pepsi][^drpepper][somethingElse] 

编辑2

如果你想标记化,按照J-_ -L建议采用scan方法,加入:

m[3].scan(/\[\^?[^\]]+\]/) 
+0

我已经在Ruby和JavaScript中尝试了这一点 - 但这是返回所有条款合并,并且只分开最后一个条款。由于它返回了所有组合条件 - 第二个例子中的'[foo] [^ apples]'和单独的最后一个术语 - '[^ apples]',我猜它能够找到匹配项,但是它的匹配项没有出现在任何地方的输出。不知道我错过了什么。 – Anurag 2011-05-20 00:30:03

+0

也许我误解了一些东西......你是否试图有效地标记每个“条款”?如果这样的正则表达式不适用于标记化部分,那么在将所有“术语”一起捕获之后,根据'] ['进行分割 - 根据我的理解,没有语言允许其正则表达式引擎中的可变数目的捕获组。我写了一个快速和肮脏的红宝石检查,我将作为一个编辑发布。告诉我,如果我误解了你的问题。 – photoionized 2011-05-20 00:46:18

+0

感谢关于拆分原始输入的建议,然后扫描分组的字符串。它的作品非常漂亮。 – Anurag 2011-05-20 01:12:01

1

这就像here一样的问题 - 你只有固定数量的捕获组。在你的情况下,我会分割字符串(例如用光离子化的方法),并做一个scan(例如(\[\^?[^\]]+\]))来获得组。

+0

@J - 谢谢。它效果很好。我会用'treetop'去创建一个小解析器来做到这一点,因为它感觉更清洁一点。感谢你的帮助。 – Anurag 2011-05-20 01:13:00