正则表达式中的look-around
发布时间:2020-12-14 02:07:06 所属栏目:百科 来源:网络整理
导读:使用向前看和上后看你可以来完成各种各样的assert来满足你的需求。 在字符串处理时,你可以向前或者向后看,同时你可以让你所看的pattern是成功或者失败。 就像Java中的assert() (?=pattern) is a positive look-ahead assertion assert(pattern match) -- (?
使用向前看和上后看你可以来完成各种各样的assert来满足你的需求。
在字符串处理时,你可以向前或者向后看,同时你可以让你所看的pattern是成功或者失败。 就像Java中的assert() (?=pattern) is a positive look-ahead assertion assert(pattern match) --> (?!pattern) is a negative look-ahead assertion assert(pattern not match) --> (?<=pattern) is a positive look-behind assertion assert(pattern match) <-- (?<!pattern) is a negative look-behind assertion assert(pattern not match) <-- look-ahead -->向前看 look-behind <--向后看 1. 寻找最后出现的字符串 这里有很多不使用左右看的方法来完成寻找最后出现的字符串, 但是如果你需要的是:最后的字符串是foo并且foo之后再也没有foo字符串了(可以有其它的字符串),你可以使用: /foo(?!.*foo)/ 正则表达式引擎会在找到foo之后使用look-around中的pattern .*foo去匹配,如果匹配到,但是因为是getative的, 所有assert失败,然后正则表达式引擎会继续查找下一个foo。 例如:foobar会匹配到第一个foo 而foobarfooeee会匹配到第二个foo 以(?<=foo)作为分隔符
Many substitutions match a chunk of text and then replace part or all of it. You can often avoid that by using look-arounds. For example,if you want to put a comma after every foo: 很多替换方法匹配一串字符的全部或者一部分。你可以使用look-around来实现。 例如,你想要在每个foo之后都加一个逗号: s/(?<=foo)/,/g; # 不使用向后看: s/foo/foo,/g or s/(foo)/$1,/g 或者给lookahead中间加一个- s/(?<=look)(?=ahead)/-/g; 需要注意的是,左右看这种方法不能有变量长度,这意味着你不能在它之后或者之内使用像(?,*,+,or {1,5}) 这样的限定符。 将lookahead替换成look-ahead
3. 匹配一个pattern但是不包含其它的pattern You might want to capture everything between foo and bar that doesn't include baz. The technique is to have the regex engine look-ahead at every character to ensure that it isn't the beginning of the undesired pattern: 你可能想匹配所有在foo和bar之间的字符串,但是foo之后不能是baz。 你可以使用下面的表达式: /foo # Match starting at foo ( # Capture (?: # Complex expression(you do not use the backreference): (?!baz) # make sure we're not at the beginning of baz #or using (?!.*baz) make sure the whole string between foo and bar not contains baz . # accept any character )* # any number of times ) # End capture bar # and ending at bar /x; foo((?:(?!baz).*))bar 不会匹配foobazddbar foo之后不知baz,所以匹配上了 如果想匹配foo和bar之间没有baz可以使用: foo((?:(?!.*baz).*))bar
4. 嵌套 look-arounds是可以嵌套的。look-arounds的自表达式会冲它上层继承开始位置,然后在这个开始位置的基础上 左右看同时不影响上层的位置,子表达式和父亲是相互独立的,它们独自维护自己的位置信息。 这个概念很简单,但是表达式很快就会变的很难懂。所有推荐对正则表达式加注释。 下面让我们来看一个正则表达式的例子。我们希望在任何分隔符(为了简单我们只用,)之后加一个空格, 但是在两个数字之间的,不加空格。 s/(?<=,# after a comma, (?! # but not matching (?<=d,) # digit-comma before,AND (?=d) # digit afterward ) )/ /gx; # substitute a space (?<=,(?!(?<=d,)(?=d))) 在,之后加空格,但是数字之间的不加
事实上你可是使用布尔代数表达式 ( NOT (a AND b) === (NOT a OR NOT b) ) 来转化上面的表达式 s/(?<=,but either (?: (?<!d,) # not matching digit-comma before | # OR (?!d) # not matching digit afterward ) )/ /gx; # substitute a space
(?<=,(?:(?<!d,)|(?!d))) 4. 捕获有时我们会在look-around中捕获大括号。你可能认为你不会用到。 但是还是请你记住: the capturing parentheses must be within the look-around expression。 从enclosing expression来看,lookaround其实没有进行匹配。 最有用的技巧是在全局匹配模式时寻找重叠的匹配。 你可以捕获子串但是不需要消耗它,然后它可以对后面的匹配有效。 或许最简单的例子就是获得所有的右边的子串 print "$1n" while /(?=(.*))/g; 注意这个模式理论上不会消耗任何一个字符,但是Perl在空匹配时会自动追加一个字符来防止无限循环。 http://www.perlmonks.org/?node_id=518444 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |