Perl中的Lookaround断言

时间:2013-06-06 06:34:26

标签: regex perl

我很困惑perl中这些外观断言的用途是什么?

这个例子:

(?=pattern)

或积极向前看。所以这是我的问题:

  1. 这些有用吗?他们使用了什么样的实例?
  2. 与问题1相关,为什么我要展望正则表达式?不是更多的工作?展望未来然后再次执行模式匹配。
  3. 如果可能,我需要一个非常明确的例子。感谢

5 个答案:

答案 0 :(得分:4)

要大写逗号之间的内容,您可以使用:

(my $x = 'a,b,c,d,e') =~ s/(?<=,)([^,]*)(?=,)/ uc($1) /eg;   # a,B,C,D,e

                  a,b,c,d,e
Pass 1 matches      -
Pass 2 matches        -
Pass 3 matches          -

如果你没有使用外观,那就是你得到的,

(my $x = 'a,b,c,d,e') =~ s/,([^,]*),/ ','.uc($1).',' /eg;   # a,B,c,D,e

                  a,b,c,d,e
Pass 1 matches     ---
Pass 2 matches         ---

前瞻不仅避免重复,没有它也行不通!


另一种常见的用法是作为等同于[^CHAR]的字符串的一部分。

foo(?:(?!foo|bar).)*bar  # foo..bar, with no nested foo or bar

您可以使用它来缩小角色类别。

\w(?<!\d)     # A word char that's not a digit.

虽然现在可以使用(?[ ... ])完成此操作。


它在更深奥的模式中也很有用。

 /a/ && /b/ && /c/

可以写成

 /^(?=.*?a)(?=.*?b).*?c/s

答案 1 :(得分:3)

lookahead可让您检查以查找模式,而不会实际匹配

执行a(?=b)时,如果a后跟b,则会匹配b注意:它与#不匹配。


所以,

1&gt;您可以使用

#hello#中提取 hello (不包含(?<=#)hello(?=#)
^(?=(.*\d){2})(?=(.*[a-z]){2}).*$

2&gt;您可以验证密码,但密码必须包含2位数字,2个字母或更多字符任何其他字符

{{1}}

尝试上面没有预见,你会意识到它的重要性

答案 2 :(得分:1)

我发现前瞻对于检查多个条件特别有用。例如,考虑一个正则表达式,它检查密码是否至少有一个小写,一个大写,一个数字和一个符号字符,并且长度至少为8个字符:

^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^a-zA-Z0-9]).{8,}$

尝试设计正则表达式来做同样的事情没有先行断言!这是可能的,但它非常麻烦。

与此同时,我发现lookbehinds对于检查边界条件特别有用 - 例如,匹配0的字符串,除非之前有另一个数字,如1000067

这些是我的体验,但当然还有更多实际用途,每个人使用工具的方式因人而异。

答案 3 :(得分:0)

使用外观的原因有很多,例如

  1. 限制被视为匹配的子字符串:s/(?<=[0-9])+(?=[0-9])/-/而不是s/([0-9])+([0-9])/$1-$2/
  2. 和各种条件:/(?=\p{Uppercase}\p{Lowercase})\p{InBasicLatin}{2,}/

答案 4 :(得分:0)

当您需要一个模式来帮助找到匹配但是您不希望模式成为捕获的一部分时,Lookaround断言非常有用。

这是一个带有先行断言的简单场景:

假设我有

my $text = '98 degrees, 99 Red Balloons, 101 Dalmatians'

我想将红色气球的数量从之前的值更改为9001,所以我使用

$text =~ s/\d+(?=Red Balloons)/9001/;