新手问题 ruby 的正则里有个前视断言,那有木有后视断言涅?

ywencn · 2012年06月23日 · 最后由 zw963 回复于 2012年06月26日 · 4560 次阅读

前视断言

前视断言表示想要知道下一个指定的是什么,但并不匹配

肯定的前视断言 (?=) 假设我们想要匹配一个数的序列,该序列以一个圆点结束,但并不想把圆点作为模式匹配的一部分

teststr="123 456 789.012"
m=/\d+(?=\.)/.match(teststr)
puts m[0] #-> 789

如果反过来,是想查序列以一个原点开始,但并不想把圆点作为模式匹配的一部分,应该怎么搞?貌似在匹配网页的时候还是蛮常用的呀。 比如要找出teststr="123 456 789.012"中的 012

共收到 10 条回复

用括号捕获就行了

[17] pry(main)> "123 456 789.012"[/(\d+)\.(\d+)/, 1]
=> "789"
[18] pry(main)> "123 456 789.012"[/(\d+)\.(\d+)/, 2]
=> "012"

你说的后视断言是这样吧;

[19] pry(main)> "123 456 789.012"[/(?<=\.)(\d+)/]
=> "012"

这个问题我见人问了很多次了.

不妨一次性全写出来, 方便大家观看:

(?<=BEFORE) RE # => 前置条件, 匹配RE, 1.9支持 RE (?=AFTER) # => 后置条件, 匹配RE, 1.8支持 (?>INNER) # => 子查询, 匹配RE, 1.9 支持.

p.s. 我可记不住这些该死的括号还有方向, 我是靠编辑器的snippet记忆的. 前置条件我简写为: <<, 后置条件我写为 >>, 子查询我写为.. , 好记吧.

puts "123 456 789.012"[/(?<=\.)(\d+)/, 1] Ruby 1.9.3测试通过, Ruby 1.8.7报SyntaxError. 正如楼上所说, Ruby 1.8不支持Lookbehind, Ruby 1.9支持. 好在现在1.9是大势所趋, 直接无视1.8.

#4楼 @zw963 子查询能否举个例子? 没见过那种RE的语法.

#6楼 @tylerlong

子查询和其他两个理解起来差不多

例如: /RE1(?>RE)RE2/

首先会匹配RE, 然后才会匹配RE1以及RE2, 而且被RE匹配过的部分, RE1和RE2就不会在匹配了.

典型的用途, 当使用前置查询时, 前置RE表达式必须是固定长度的RE, 否则会出错. 如果前置是一个无法确定数量的pattern, 只能在前置条件中, 嵌套一个子查询.

#7楼 @zw963 好详细,看来1.9的知识还得再深入下,regexp就有好多新亮点

#7楼 @zw963 你描述的概念学名叫做Atomic Grouping, "An atomic group is a group that, when the regex engine exits from it, automatically throws away all backtracking positions remembered by any tokens inside the group. Atomic groups are non-capturing. The syntax is (?>group). " 我的理解是它主要用于在特定情况下提高正则解析性能(通过抛弃backtracking positions).

#9楼 @tylerlong

没错, 就是变相的终止了字符串的 backtracking, 准确地说, 这都不算是一个断言.

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册