Lookahead/lookbehind are modifiers that tell your query that the saerch string is a match only if it is or is not (positive or negative) followed or preceeded, repectively, by some other text that you specify.
Peter Kahrel has written an excellent primer on GREP in InDesign that is very inexpensive and availble from O'Reilly.
Scott, this is unfair, since Adobe's documentation gives no good explanation for what these things mean.
I personally like the perl documentation: http://perldoc.perl.org/perlre.html#Look-Around-Assertions:
Look-around assertions are zero-width patterns which match a specific pattern without including it in
$&. Positive assertions match when their subpattern matches, negative assertions match when their subpattern fails. Look-behind matches text up to the current match position, look-ahead matches text following the current match position.
A zero-width positive look-ahead assertion. For example,
/\w+(?=\t)/matches a word followed by a tab, without including the tab in
A zero-width negative look-ahead assertion. For example
/foo(?!bar)/matches any occurrence of "foo" that isn't followed by "bar". Note however that look-ahead and look-behind are NOT the same thing. You cannot use this for look-behind.
If you are looking for a "bar" that isn't preceded by a "foo",
/(?!foo)bar/will not do what you want. That's because the
(?!foo)is just saying that the next thing cannot be "foo"--and it's not, it's a "bar", so "foobar" will match. Use look-behind instead (see below).
A zero-width positive look-behind assertion. For example,
/(?<=\t)\w+/matches a word that follows a tab, without including the tab in
$&. Works only for fixed-width look-behind.
There is a special form of this construct, called
\K, which causes the regex engine to "keep" everything it had matched prior to the
\Kand not include it in
$&. This effectively provides variable-length look-behind. The use of
\Kinside of another look-around assertion is allowed, but the behaviour is currently not well defined.
For various reasons
\Kmay be significantly more efficient than the equivalent
(?<=...)construct, and it is especially useful in situations where you want to efficiently remove something following something else in a string. For instance
can be rewritten as the much more efficient
A zero-width negative look-behind assertion. For example
/(?<!bar)foo/matches any occurrence of "foo" that does not follow "bar". Works only for fixed-width look-behind.