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

Re: triviality regarding $# counts



On Sat, Apr 13, 2024 at 8:14 AM Ray Andrews <rayandrews@xxxxxxxxxxx> wrote:
>
> Anyway, it comes clear: '${(@f)....}' doesn't ADD (or retain) newlines it removes them!  (Tho splitting the array where they used to be.) Doesn't need them cuz elements aren't separated by newlines (like I thought) but by ... however it's done.

(Liberties taken with historical accuracy below, do not feel compelled
to leap in with sequencing corrections, etc.)

In the beginning, there were only environment strings ($SHELL, $PATH,
etc.) and positional parameters ($1, $2, etc.).  When a command was
run, it got its arguments as an "array" of positional parameters.
This is how "variables" came to be called "parameters" in shell
jargon.  This mapped directly onto C main() argc ($#) and argv[] ($@)
with the phantom $0 as the name of the command.

Referencing an environment string or an individual positional
parameter without quoting in a command argument caused the value to be
split on whitespace (as defined by the value of $IFS) to convert it
into an argv array.  Putting it in double quotes protected it from
that splitting but still permitted it to be replaced by its value.
Single quotes were for literal strings.  To reference an entire argv
without further splitting but also without losing its array property,
"$@" got the special meaning to quote each element individually.  $*
would give the entire argv but also split it further on whitespace,
and "$*" gave the entire argv joined back together with with spaces to
make it a single string.

It follows from this that it's useful to be able to assign names to
strings other than environment strings and to arrays other than the
positional parameters.  Thus we get scalar parameters and array
parameters, but they still follow the rules corresponding to
environment strings and positional parameters including the $* and $@
references to the full arrays, except now the name is added as in
${ary[3]} and ${ary[*]} and ${ary[@]}.  From this point forward shells
began to vary on details like whether named arrays begin with index 0
or 1 and whether it was necessary to wrap the reference in braces and
(in zsh's case) whether splitting on whitespace happens by default.

The salient point here is that regardless of the internal
representation of an array, you can think of it like an argv[] in C.
The elements are separated by conceptually being different string
pointers, and anything you "see" from e.g. "typeset -p" is language
syntax, not representation.

When you use (f) and other syntax to split something, you're creating
(temporarily) that same kind of array.  It might collapse to a string
again almost immediately based on context, which is why you might need
e.g. (@f) to specifically preserve it, but it exists however briefly
in that form.

>  Single quotes indicate elements.

Thus, that's an effect of "typeset -p" rather than anything about the
internal representation.




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