2016-07-26 107 views
0

我正在嘗試構造一個正則表達式,它會在最後一次出現的數字前後分割。我希望得到:正則表達式得到最後一次出現前後的所有內容

"index100.html"   # => ["index", "100", ".html"] 
"page.php?id=100"  # => ["page.php?id=", "100", ""] 
"page.php?f=5&page=295" # => ['page.php?f=5&page=', 295, ''] 

這裏是我想出了正則表達式:

regex = /([^0-9]+|^)(\d+?)([^0-9]+|$)/ 

它適用於前兩個例子,但不是最後一個。我得到結果:

["page.php?f=", 5, "&page="] 

如何修改正則表達式使其工作的第三種情況?

+0

嘗試此'(。*)(\ d +)(。*)' – sln

+3

的['(\ d +) (。*)'](http://rubular.com/r/orRN2ecoQk)將不起作用。 –

+0

爲什麼不是哥們?你說的對,我的錯。 – sln

回答

3

您可以充分利用.*貪婪的匹配,但與負回顧後(?<!\d)遏制它,以確保您的數字去年整塊匹配:

/(.*)(?<!\d)(\d+)(.*)/ 
^^^^^^^^^^^  

regex demo。或者,您可以在開始和結束處添加\A\z錨。

詳細

  • (.*) - 除換行符以外,儘可能多的,0個或多個字符匹配到最後一個
  • (?<!\d)(\d+) - 這是之前沒有以數字1 +數字
  • (.*) - 該行的其餘部分。

要匹配換行符,請在最後一個正則表達式分隔符後面添加m修飾符。

+0

鑑於第一個段不應該爲空,您可以將非數字作爲第一個段的最後一部分。 – sawa

+0

@sawa:我在這裏依靠回溯,它應該做得很好。當我開始複雜化模式時,人們通常會大喊大叫。 –

3

另一種方式沒有向後看。

((?:\d*\D)*)(\d+)(.*)

另一個沒有回顧後
這僅僅是儘可能快地使用回顧後
,但如果你沒有它,像JS,這樣效果更好

(.*(?:\D|^))(\d+)(.*)

+0

這裏假定除了最後一個號碼以外的號碼不能有多個數字。我不認爲這是一個安全的假設。如何用'*'替換'?'? –

+0

@TimPietzcker - 修正.. – sln

+0

這兩個正則表達式是不等效的:第二個需要在數字之前的至少一個字符,或數量必須在該行的開頭。這就是爲什麼我不會比較表現。 –

1
"index100.html" 
.partition(/\d+(?=\D*\z)/) # => ["index", "100", ".html"] 

"page.php?id=100" 
.partition(/\d+(?=\D*\z)/) # => ["page.php?id=", "100", ""] 

"page.php?f=5&page=295" 
.partition(/\d+(?=\D*\z)/) # => ["page.php?f=5&page=", "295", ""] 
+0

雖然代碼經常爲自己說話,但最好向代碼添加一些解釋。這會在審查隊列中彈出,因爲只有代碼的答案傾向於。 – Will

0
def split_it(str) 
    str.reverse.partition(/\d+/).reverse.map(&:reverse) 
end 

split_it "index100.html" 
    #=> ["index", "100", ".html"] 
split_it "page.php?id=100" 
    #=> ["page.php?id=", "100", ""] 
split_it "page.php?f=5&page=295" 
    #=> ['page.php?f=5&page=', 295, ''] 
是0

str = "page.php?f=5&page=295" 

的步驟如下:(。*)

s = str.reverse 
    #=> "592=egap&5=f?php.egap" 
a = s.partition(/\d+/) 
    #=> ["", "592", "=egap&5=f?php.egap"] 
b = a.reverse 
    #=> ["=egap&5=f?php.egap", "592", ""] 
b.map(&:reverse) 
    #=> ["page.php?f=5&page=", "295", ""] 
相關問題