2014-12-28 18 views
0

這就是我正在做的事情:在ruby中,如何使用1到12的數字使用string.scan(/ regex /)方法?

c.scan(/[1-9]|1[0-2]/) 

出於某種原因,它只返回編號從1到9,而忽略第二部分。我嘗試了一點點,似乎只有在[1-9]部分不包括1的情況下,方法纔會搜索10-12,例如,c.scan(/ [2-9] | 1 [0-2] /) 會做。是什麼原因?

P.S.我知道這種方法缺乏向後看,並且會搜索數字和「數字的一部分」

+0

'c.scan(/ \ b10 | 11 | 12 | \ d \ b /)'很好地讀,imo。 –

+0

@AvinashRaj,啊,是的。謝謝。我會留下評論,因爲它和你的可能具有教育價值,特別是那些像我一樣,有時會濫用'\ b'的人。 –

+0

啊,是的,@AvinashRaj。謝謝。讓我把它改成'c.scan(/ \ b(?:\ d | 10 | 11 | 12)\ b /)'。 –

回答

0

|從左到右匹配,並且右側的第一部分(1)始終與左側匹配。反轉它們:

c.scan(/1[0-2]|[1-9]/) 
+0

我犯了一個類似的錯誤,忘記同時包含一個非捕獲組和'\ b's(或lookarounds):'「100」.scan(/ 1 [0-2] | [1-9]/)#=> [「10」]','「101」.scan(/ 1 [0-2] | [1-9] /)#=> [「10」,「1」]'。 –

+0

@CarySwoveland:提問者沒有要求尋找問題(並在問題結尾做了具體的說明),所以沒有錯。 – Ryan

+0

我錯過了,但無論如何,它只是'\ b'的替代品。你是什​​麼意思,「沒有錯」?當然,OP不希望''101''變成'[「10」,「1」]或者「13」'變成'[「1」,「3」]'。 –

3

更改模式的順序並在必要時添加字邊界。

c.scan(/\b(?:1[0-2]|[1-9])\b/) 

首先使用|之前的模式。所以在我們的例子中,它匹配所有從10到12的數字。之後,使用下一個模式,即|之後的一個模式,現在匹配所有其餘的數字範圍從1到9.請注意,這將匹配959也。所以我建議你把你的模式放在一個捕獲或不捕獲組中,並在該組之前和之後添加單詞邊界\b匹配一個單詞字符和一個非單詞字符)。

DEMO

+1

我只想指出,使用非捕獲組給出了一個稍微不同的結果,我認爲這通常會更好一些:'c =「13 123 1 23 11 7 111 31」; c.scan(/ \ b(1 [0-2] | [1-9])\ b /)#=> [[「1」],[「11」],[「7」]]; c.scan(/ \ b(?:1 [0-2] | [1-9])\ b /)#=> [「1」,「11」,「7」]'。 –

+0

謝謝補充...我不認爲,使用捕獲組會返回一個多維數組ruby .. –

0

這裏是你可以考慮1到12之間提取數的另一種方法(假設這是你想要做什麼):

c = '14 0 11x 15 003 y12' 
c.scan(/\d+/).map(&:to_i).select { |n| (1..12).cover?(n) } 
    #=> [11, 3, 12] 

我返回一個整數數組,而不是字符串,認爲可能會更有用,但如果你想要字符串:

c.scan(/\d+/).map { |s| s.to_i.to_s } 
.select { |s| ['10', '11', '12', *'1'..'9'].include?(s) } 
    #=> ["11", "3", "12"] 

我看到這種方法的幾個優點,與使用單個r egex:

  • 它很容易理解;
  • 正則表達式很簡單;
  • 如果允許值發生變化,很容易修改;和
  • 它可以分成三個部分,以便於測試。