From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21561 invoked from network); 8 Feb 2002 21:35:23 -0000 Received: from sunsite.dk (130.225.247.90) by ns1.primenet.com.au with SMTP; 8 Feb 2002 21:35:23 -0000 Received: (qmail 2241 invoked by alias); 8 Feb 2002 21:35:11 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 16595 Received: (qmail 2221 invoked from network); 8 Feb 2002 21:35:09 -0000 Date: Fri, 8 Feb 2002 21:35:07 +0000 (GMT) From: Bart Schaefer Sender: lantern@brasslantern.com To: Derek Peschel cc: zsh-workers@sunsite.dk Subject: Re: parameter substitution won't double backslashes in values In-Reply-To: <20020208012944.A8380@eskimo.eskimo.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII 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: y='\' 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.