With the look-ahead and look-behind constructs documented in perlre.html#Extended-Patterns, you can "roll your own" zero-width assertions to fit your needs. You can look forward or backward in the string being processed, and you can require that a pattern match succeed (positive assertion) or fail (negative assertion) there.
/foo(?!.*foo)/The regular expression engine will do its best to match .*foo, starting at the end of the string "foo". If it is able to match that, then the negative look-ahead will fail, which will force the engine to progress through the string to try the next foo.
s/(?<=foo)/,/g; # Without lookbehind: s/foo/foo,/g or s/(foo)/$1,/gor to put the hyphen in look-ahead:
s/(?<=look)(?=ahead)/-/g;This kind of thing is likely to be the bulk of what you use look-arounds for. It is important to remember that look-behind expressions cannot be of variable length. That means you cannot use quantifiers (., +, or {1,5}) or alternation of different-length items inside them.
/foo # Match starting at foo (?: # Complex expression: (?!baz) # make sure we're not at the beginning of baz . # accept any character )* # any number of times bar # and ending at bar /x;
The concept is pretty simple, but the notation becomes hairy very quickly, so commented regular expressions are recommended. Let's look at the real example of [id://319742]. The poster wants to put a space after any comma (punctuation, actually, but for simplicity, let's say comma) that is not nestled between two digits. Building up the s/// expression:
s/(?<=, # after a comma,
(?! # but not matching
(?<=\d,) # digit-comma before, AND
(?=\d) # digit afterward
)
)/ /gx; # substitute a space
Note that multiple lookarounds can be used to enforce multiple conditions at the same place, like an AND condition that complements the alternation (vertical bar)'s OR. In fact, you can use Boolean algebra ( NOT (a AND b) === (NOT a OR NOT b) ) to convert the expression to use OR:
s/(?<=, # after a comma, but either
(?:
(?
Capturing
It is sometimes useful to use capturing parentheses within a look-around. You might think that you wouldn't be able to do that, since you're just browsing, but [478043|you can]. But remember: the capturing parentheses must be within the look-around expression; from the enclosing expression's point of view, no actual matching was done by the zero-width look-around.
perlmonks.org content © perlmonks.org and Roy Johnson
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03