2016-07-26 63 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", ""] 
相关问题