2014-03-13 82 views
0

我有以下的正則表達式:不知道爲什麼正則表達式是不工作

a=/item\/([0-9]+)\)/.match("item/123) and also item/245)") 

我試圖拔出所有鏈接的項目ID在一個字符串,像這樣:

[123,245] 

但它返回

<MatchData "item/123)" 1:"123"> 

(即只有第一個)。我怎樣才能讓它返回兩個ID(作爲兩個MatchData的一部分或通過其他方法)?我想我需要指定貪婪但不確定。

回答

3

你可以做如下使用scan

如果模式不包含組,每個人結果由匹配的字符串,$ &的。 如果模式包含組,每個單獨的結果本身就是一個數組,每個組包含一個條目。

"item/123) and also item/245)".scan(/item\/([0-9]+)\)/).flatten 
# => ["123", "245"] 
s = "item/123) and also item/245)" 
s.scan(/item\/([0-9]+)\)/).flatten.map(&:to_i) # to get them as integers 
# => [123, 245] 

正如你已經創建了一個捕獲組,從而得到結果只有一個:

a = /item\/([0-9]+)\)/.match("item/123) and also item/245)") 
a.captures # => ["123"] 

看也是方法captures

+0

thx,看起來不錯。 – timpone

+1

+1'flatten'。 –

+0

有沒有辦法做多重捕捉?必須等待幾個才能接受 – timpone

1

您可以使用此方法scan

a = "item/123) and also item/245)".scan(/item\/([0-9]+)\)/) 

將返回:

[["123"], ["245"]] 
+0

我自己先... 15秒:-) –

+0

ahh ... thx;我很接近 – timpone

+2

小心你的模式中的捕獲。 OP需要一個平坦的數組,並且捕獲將導致'scan'返回一個數組數組。 –

4

而不捕獲不必要的東西:如果你想要的是IDS

"item/123) and also item/245)".scan(%r{(?<=item/)\d+(?=\))}) 
# => ["123", "245"] 
2

,並有文本沒有對方號碼,就可以大大簡化您的模式:

"item/123) and also item/245)".scan(/\d+/) # => ["123", "245"] 

或者,如果你想整數,而不是字符串:

"item/123) and also item/245)".scan(/\d+/).map(&:to_i) # => [123, 245] 

如果你想避免一些數字,你可以測試「指數/」後面跟一個數字,用正面看,背後@sawa建議,或使用的東西沿着這些路線:

"item/123) and also item/245)".scan(%r[item/\d+]).map{ |s| s[/\d+/] } # => ["123", "245"] 

或者:

"item/123) and also item/245)".scan(%r[item/\d+]).map{ |s| s[/\d+/].to_i } # => [123, 245] 

打破了,所以你可以看到發生了什麼:

"item/123) and also item/245)".scan(%r[item/\d+]) # => ["item/123", "item/245"] 
"item/123"[/\d+/] # => "123" 

就我個人而言,我喜歡@ sawa的回答,因爲它很乾淨而且簡單,只會查找「item /」後面的數字,並避免需要強制後續的捕獲組flatten。我只是想展示如何使用更簡單的模式來做到這一點。

相關問題