Re: [MacPerl-AnyPerl] negative lookahead problem

[email protected] (Bart Lateur) Sun, 12 Aug 2001 15:13:41 +0200
Newsgroups perl.macperl.anyperl
Organization MediaMind
Message-ID <[email protected]>
On Sat, 11 Aug 2001 15:26:16 +0200, allan wrote:

>ronald's script works out of the box. but again im not sure i understand
>why. for instance, what is the difference between | and || (precedence
>perhaps?) and why exactly are we using the /e modifier?

Well, Ronald explains the "/e" and "||' quite well, so let me focus on
that "|" part... take this as an example.

	/(")|(.)/

Attempts at matching are tried from left to right. So, this regex will
attempt to match, for every character, a quote first, and *if that
fails*, any character but newline. If a quote is found, the first
subpattern matches, and the rest isn't even tried (even though it would
have matched). So in that case, $1 is set to what is matched, the quote,
and $2 is undef.

If there was another (normal) character, the first subpattern would have
failed, but the second would have matched. In that case, $1 would be
undef, and $2 would contain the matched character.

What if it was a newline? Well: both subpatterns would have failed, the
regex start-of-match pointer would have been increased, and the whole
circus begins again: first try for quote, next try for any normal
character... etc. until one of the two is found, or there are no more
characters to test.

A more complex example, is this:

	/(".*?")|(\s+)/

This will attempt to match a quoted string, or whitespace. For a quoted
string, $1 will contain it, including the quotes, and $2 is undef; for a
whitespace character string, $2 will contain it, and $1 is undef. Note
that the quoted string can contain whitespace characters as well, so
this serves as a good method to distinguish whitespace between quotes
(in $1) and bare whitespace (in $2).

So, let's apply this:

	s/(".*?")|(\s+)/$1 || ' '/ge;

If it matches a quoted string, $1 will set to it; since it contains at
least a quote character, it will be interpreted as true. So the RHS,
which is executed as perl code for every match, evaluation will stop at
the ||, the value of $1 is retained. Thus, quoted strings are preserved.

If instead, bare whitespace is found, $1 is undef (thus false), and

	$1 || ' '

will evaluate to a space.

Net result: all whitespace is replaced by a single quote, except in
quoted strings.

Your problem neatly maps into this category.

-- 
	Bart.