Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: parameter substitution won't double backslashes in values

On Fri, 8 Feb 2002, Derek Peschel wrote:

> I was afraid of this... parameter expansion is obviously a complicated
> operation.

Zsh's very own 12-step program.

> For example, I only have a guess as to why these examples do what they do.
> > x="/usr/home/dpeschel"
> > print ${(q)x//t}
> /usr/home/dpeschel
> > print ${(q)x/\/t}
> t/usr/home/dpeschel
> The first example has "//" (as in global search-and-replace) followed by
> a search pattern of "t", without the "/" to delimit the replacement pattern
> or the pattern itself.

Right.  Try it with "e" instead, you get `/usr/hom/dpschl'.  By the way,
the (q) there isn't doing anything useful (in this specific example).

> The second example has "/" (as in non-global search-and-replace) followed
> by an empty search pattern, then "\/" which ends the search pattern,
> then a replacement pattern of "t".
> Is this true?

Yes.  To match an actual slash, you need ${x/\\//t} or ${x//\\//t} to do
it globally.

In ${x/\/t} the first parse of the outer ${...} gives something like "x
slash escaped-slash t".  The escaped-slash ends the pattern because, if
you'd put it in double quotes like "${x/a/b}" the double-quotes will also
cause the second slash to appear to be an escaped-slash, so the parser
compensates by ending the pattern at any escaped-slash.  This is where the
fun begins.

In ${x/\\//t} the parse is "x slash backslash slash slash t" (the double
backslash becomes a single backslash) so *now* when the pattern is parsed
the backslash+slash become a slash and the third slash ends the pattern.

So in ${x//\\\/t}, the triple backslash makes it through as a single
backslash, but in ${x//\\\\/t} the third slash gets escaped and becomes
part of the pattern, which is completely not what you expect.  Further, if
you take *either* the triple-backslash form *or* the quadruple, and put it
in double quotes, the third slash is again part of the pattern -- which
means that in double quotes there's no way to cause a backslash to be part
of the pattern (which is what I think is a bug), except to do this trick:

print "${x/$y/t}"

That works because the $y is not expanded until after the end of the
pattern have been identified.

It gets even stranger if we start discussing how backslashes in the
replacement affect the parsing of the closing curly-brace, but I don't
have time to go there.

Messages sorted by: Reverse Date, Date, Thread, Author