zsh-workers
 help / color / mirror / code / Atom feed
* BUG? - 4.0.2 - parameter substitution won't double backslashes in values
@ 2002-02-07  4:39 Derek Peschel
  2002-02-07 10:33 ` Peter Stephenson
  2002-02-07 10:44 ` BUG? - 4.0.2 - " Sven Wischnowsky
  0 siblings, 2 replies; 9+ messages in thread
From: Derek Peschel @ 2002-02-07  4:39 UTC (permalink / raw)
  To: zsh-workers

I want to write the elements of $dirstack out to a file, separated by
newlines.  If an element in $dirstack contains a newline, I want to write
a backslash before the newline in the file.  Parameter substitution
managed that:

print ${dirstack[0]/
/\\\\
}

But I also want to double any backslashes in $dirstack, and I haven't
managed to do that yet with parameter substitution.  The backslash
sequences in the parameter seem to be interpreted before substitution
happens.

Suppose I have a subdirectory "a\bc" under my home directory.

print $dirstack[0]
/usr/home/dpeschel/ac
["\b" is a backspace]

print ${dirstack[0]/\\/\\\\}
/usr/home/dpeschel/ac
[no change]

print ${dirstack[0]/\\\\/\\\\\\\\}
/usr/home/dpeschel/ac
[no change]

print ${dirstack[0]/b/t}
/usr/home/dpeschel/a	c
[the "\b" gets changed to "\t" which is a tab]

Then I thought of using a single backslash -- given that escape sequences
happen "at a lower level" than parameter substitution, and parameter-
substitution backslashes must be quoted, it makes a kind of sense that
an unquoted backslash would affect the version of the value with un-
processed escape sequences.

The result was really weird:
print ${dirstack[0]/\/t}
t/usr/home/dpeschel/ac

If there's another way to do this, aside from parameter substitution,
that would be OK.

I haven't yet tackled reading the items back from the file, but obviously
writing has to work first.

-- Derek


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: BUG? - 4.0.2 - parameter substitution won't double backslashes in values
  2002-02-07  4:39 BUG? - 4.0.2 - parameter substitution won't double backslashes in values Derek Peschel
@ 2002-02-07 10:33 ` Peter Stephenson
  2002-02-07 13:19   ` Derek Peschel
  2002-02-07 10:44 ` BUG? - 4.0.2 - " Sven Wischnowsky
  1 sibling, 1 reply; 9+ messages in thread
From: Peter Stephenson @ 2002-02-07 10:33 UTC (permalink / raw)
  To: Zsh hackers list

Derek Peschel wrote:
> I want to write the elements of $dirstack out to a file, separated by
> newlines.  If an element in $dirstack contains a newline, I want to write
> a backslash before the newline in the file.  Parameter substitution
> managed that:
> 
> print ${dirstack[0]/
> /\\\\
> }
>...

I haven't looked at this in detail, but you might be coming a bit unstuck
by using `print' instead of `print -r'.  The latter will avoid interpreting
the backslashes at that point, which is almost certainly closer to what you
want.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 392070


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: BUG? - 4.0.2 - parameter substitution won't double backslashes in values
  2002-02-07  4:39 BUG? - 4.0.2 - parameter substitution won't double backslashes in values Derek Peschel
  2002-02-07 10:33 ` Peter Stephenson
@ 2002-02-07 10:44 ` Sven Wischnowsky
  1 sibling, 0 replies; 9+ messages in thread
From: Sven Wischnowsky @ 2002-02-07 10:44 UTC (permalink / raw)
  To: zsh-workers


Derek Peschel wrote:

> I want to write the elements of $dirstack out to a file, separated by
> newlines.  If an element in $dirstack contains a newline, I want to write
> a backslash before the newline in the file.  Parameter substitution
> managed that:

If what you're really after is being able to dump the value of
$dirstack to a file to be able to restore it from that file later, you
could just use some trickery:

  dump_dirstack() {
    print -lr 'dirstack=(' "${(q@)dirstack}" ')' > ~/.dirstack
  }

  # pretty useless wrapper function...

  restore_dirstack() {
    . ~/.dirstack
  }

Or some such.

A generic function to store an array (1st arg) to a file (2nd arg)
would be:

  dump_array() {
    print -lr "$1=(" "${(P@q)1}" ')' > $2
  }

Hope that helps...


Bye
  Sven

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: BUG? - 4.0.2 - parameter substitution won't double backslashes in values
  2002-02-07 10:33 ` Peter Stephenson
@ 2002-02-07 13:19   ` Derek Peschel
  2002-02-07 19:20     ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Derek Peschel @ 2002-02-07 13:19 UTC (permalink / raw)
  To: zsh-workers

On Thu, Feb 07, 2002 at 10:33:55AM +0000, Peter Stephenson wrote:
> Derek Peschel wrote:

> > I want to write the elements of $dirstack out to a file, separated by
> > newlines.  If an element in $dirstack contains a newline, I want to write
> > a backslash before the newline in the file.  Parameter substitution
> > managed that:
> > 
> > print ${dirstack[0]/
> > /\\\\
> > }
> >...
> 
> I haven't looked at this in detail, but you might be coming a bit unstuck
> by using `print' instead of `print -r'.  The latter will avoid interpreting
> the backslashes at that point, which is almost certainly closer to what you
> want.

Good advice.  I did have to read the sentence a couple of times to be
absolutely sure you were telling me to use "print -r".

But I would still expect some change (a backspace should change to "\b" when
using "print", or "\b" should change to "\\b" when using "print -r").
And there is absolutely none as far as I can tell.  And I think that's odd.

-- Derek


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: BUG? - 4.0.2 - parameter substitution won't double backslashes in values
  2002-02-07 13:19   ` Derek Peschel
@ 2002-02-07 19:20     ` Bart Schaefer
  2002-02-07 20:22       ` Derek Peschel
  0 siblings, 1 reply; 9+ messages in thread
From: Bart Schaefer @ 2002-02-07 19:20 UTC (permalink / raw)
  To: Derek Peschel; +Cc: zsh-workers

On Thu, 7 Feb 2002, Derek Peschel wrote:

> But I would still expect some change (a backspace should change to "\b" when
> using "print", or "\b" should change to "\\b" when using "print -r").

Um, no.  With "print" a "\b" changes to backspace; with "print -r", "\b"
remains "\b".  In either case a literal backspace remains a backspace.

If you want to convert backspace and other "control characters" to a
visible representation, you can use the (V) parameter flag:

zsh% bs=$(print -n '\b')
zsh% print ${(V)bs}
^H

Note that the conversion from '\b' to backspace was done by print, and the
conversion from backspace to ^H was done by parameter expansion.  There is
no built-in mechanism to convert from backspace to '\b'.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: BUG? - 4.0.2 - parameter substitution won't double backslashes in values
  2002-02-07 19:20     ` Bart Schaefer
@ 2002-02-07 20:22       ` Derek Peschel
  2002-02-07 21:00         ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Derek Peschel @ 2002-02-07 20:22 UTC (permalink / raw)
  To: zsh-workers

On Thu, Feb 07, 2002 at 07:20:38PM +0000, Bart Schaefer wrote:
> On Thu, 7 Feb 2002, Derek Peschel wrote:

> > But I would still expect some change (a backspace should change to "\b" when
> > using "print", or "\b" should change to "\\b" when using "print -r").
> 
> Um, no.  With "print" a "\b" changes to backspace; with "print -r", "\b"
> remains "\b".  In either case a literal backspace remains a backspace.
> 
> If you want to convert backspace and other "control characters" to a
> visible representation, you can use the (V) parameter flag:
> 
> zsh% bs=$(print -n '\b')
> zsh% print ${(V)bs}
> ^H
> 
> Note that the conversion from '\b' to backspace was done by print, and the
> conversion from backspace to ^H was done by parameter expansion.  There is
> no built-in mechanism to convert from backspace to '\b'.

Maybe my explanation was too complicated, or probably you missed the
beginning of the thread.

I have a string containing the characters "a", backslash, "b", "c".
When I print it using "print", it appears as "ac" (because the backslash,
"b" gets converted to backspace).  When I print it using "print -r",
it appears as "a\bc".

I want to use parameter substitution to convert the backslash to two
backslashes.  I haven't managed it yet -- that's what I was referring
to when I wrote "but I would still expect some change".

Assuming I did manage it, I would have the five characters "a", backslash,
backslash, "b", "c".  If I printed _them_ using "print", I would expect
to see "a\bc" and if I printed them using "print -r" I would expect to
see "a\\bc".

My first post has all the examples in it.  Please see that one.

-- Derek


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: BUG? - 4.0.2 - parameter substitution won't double backslashes in values
  2002-02-07 20:22       ` Derek Peschel
@ 2002-02-07 21:00         ` Bart Schaefer
  2002-02-08  9:29           ` Derek Peschel
  0 siblings, 1 reply; 9+ messages in thread
From: Bart Schaefer @ 2002-02-07 21:00 UTC (permalink / raw)
  To: Derek Peschel; +Cc: zsh-workers

On Thu, 7 Feb 2002, Derek Peschel wrote:

> Maybe my explanation was too complicated, or probably you missed the
> beginning of the thread.

I saw the beginning of the thread, and I saw Sven's answer, which didn't
seem to bear repeating, so I was responding only to the parenthetical
comment about backspace changing to "\b".  As Sven's answer apparently
does bear repeating:

> I have a string containing the characters "a", backslash, "b", "c".
[...]
> I want to use parameter substitution to convert the backslash to two
> backslashes.

You *probably* want the (q) parameter flag:

zsh% x='a\bc'
zsh% print ${(q)x}
a\bc
zsh% print -r ${(q)x}
a\\bc

However, (q) will also insert a backslash in front of any other character
that is special to the shell parser.  If you want *only* to double all the
backslashes, you need one of:

zsh% print -r ${x//\\\/\\\\}
a\\bc
zsh% print -r ${x:gs/\\/\\\\\\\\}
a\\bc

The reason you need three backslashes as the pattern in the first case is
rather complicated and could possibly be considered a bug; it has to do
with using glob-pattern interpretation in ${x//...}.  The reason you need
eight backslashes as the replacement in the second case is a lot easier to
explain; the eight are reduced to four by the initial parse of the shell
command line, and then reduced again to two when the :gs replacement
occurs.

The second one is probably more reliable, as it works the same even if the
expansion is enclosed in double quotes.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: parameter substitution won't double backslashes in values
  2002-02-07 21:00         ` Bart Schaefer
@ 2002-02-08  9:29           ` Derek Peschel
  2002-02-08 21:35             ` Bart Schaefer
  0 siblings, 1 reply; 9+ messages in thread
From: Derek Peschel @ 2002-02-08  9:29 UTC (permalink / raw)
  To: zsh-workers

On Thu, Feb 07, 2002 at 09:00:05PM +0000, Bart Schaefer wrote:
> On Thu, 7 Feb 2002, Derek Peschel wrote:

> > Maybe my explanation was too complicated, or probably you missed the
> > beginning of the thread.
> 
> I saw the beginning of the thread, and I saw Sven's answer, which didn't
> seem to bear repeating, so I was responding only to the parenthetical
> comment about backspace changing to "\b".  As Sven's answer apparently
> does bear repeating:

Thanks for clearing that up.   I apologize if I was a bit rude.  Sven's
answer is the most practical for my needs.

> However, (q) will also insert a backslash in front of any other character
> that is special to the shell parser.  If you want *only* to double all the
> backslashes, you need one of:
> 
> zsh% print -r ${x//\\\/\\\\}
> a\\bc
> zsh% print -r ${x:gs/\\/\\\\\\\\}
> a\\bc
> 
> The reason you need three backslashes as the pattern in the first case is
> rather complicated and could possibly be considered a bug; it has to do
> with using glob-pattern interpretation in ${x//...}.  The reason you need

I was afraid of this... parameter expansion is obviously a complicated
operation.  (I took "BUG? - " out of the subject because I haven't found
a problem that I know how to identify or fix.  But not being able to
understand the syntax is somewhat of a bug in itself.)

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.

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?

-- Derek


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: parameter substitution won't double backslashes in values
  2002-02-08  9:29           ` Derek Peschel
@ 2002-02-08 21:35             ` Bart Schaefer
  0 siblings, 0 replies; 9+ messages in thread
From: Bart Schaefer @ 2002-02-08 21:35 UTC (permalink / raw)
  To: Derek Peschel; +Cc: zsh-workers

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.


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2002-02-08 21:35 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-02-07  4:39 BUG? - 4.0.2 - parameter substitution won't double backslashes in values Derek Peschel
2002-02-07 10:33 ` Peter Stephenson
2002-02-07 13:19   ` Derek Peschel
2002-02-07 19:20     ` Bart Schaefer
2002-02-07 20:22       ` Derek Peschel
2002-02-07 21:00         ` Bart Schaefer
2002-02-08  9:29           ` Derek Peschel
2002-02-08 21:35             ` Bart Schaefer
2002-02-07 10:44 ` BUG? - 4.0.2 - " Sven Wischnowsky

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).