zsh-users
 help / color / mirror / code / Atom feed
From: "Mark J. Reed" <markjreed@gmail.com>
To: zsh-users@zsh.org
Subject: Re: triviality regarding $# counts
Date: Sat, 13 Apr 2024 13:19:43 -0400	[thread overview]
Message-ID: <CAA=-s3wwLUMexvh4aiOmLSWs4T2HE+80AFE63f50ffMTPprppQ@mail.gmail.com> (raw)
In-Reply-To: <a7d236f9-0a40-4fc8-ab8f-2db9ce6edda7@eastlink.ca>

[-- Attachment #1: Type: text/plain, Size: 7123 bytes --]

Hm.

*typeset* -ga aaa=(*"*

*abc*


*    def ghi*

*    jkl mno*


*    pqr*

*"*)

This makes *aaa* an array with a grand total of 1 element. Then you do this:

redline *"linecount of aaa is: *$#aaa* ... Single element!"*


Your prefix text is wrong; calling  *$# *a "linecount" is a gross
mischaracterization. It never ever ever counts lines.  Never. It counts
characters on a scalar variable, elements of an array.  Lines have nothing
to do with it.

There are various transformations you can do that will map between lines on
the one hand and array elements on the other, but that's always some
command or special expansion flag doing an explicit transformation of the
data - which is to say, changing it. Inside an array there is no concept of
"lines" anywhere. By the same token, a piece of text containing newlines is
not inherently any sort of array at all. (Well, zsh lets you treat a
non-array variable as an array of individual characters, so in that sense
it is an array, but each character is its own element in that case, and
newlines are not in any way special.)

After your above declaration, the variable *aaa* is an array. The
parentheses in the assignment would make it one even if you hadn't
done *typeset
-a*. Unless you un-array-ify the varaible, *$#aaa* will always be *the
number of elements in the array*. It doesn't matter whether any of those
elements contain newlines or not.  Your initialization has exactly one
element, so *$#aaa* is 1. End of story.

You display things with *print -l* *$array* a lot; that's one of those
transformations I mentioned above. When you do that to an array (and *printf
'%\n' "${array[@]}"* does much the same thing in a POSIX-standard way), you
will get output that *starts *each element of the array on a separate line.
But that's all it does. Any newlines inside any of the array elements still
show up as newlines in the output. So there is no guarantee that e.g. *print
-l $ary | wc -l * will produce the same number as *$#ary*.  In your
*aaa* example,
*print -l $aaa *gets you 8 lines. But it's still a single-element array.
There is no *$aaa[put anything in here]* expression that will isolate any
of the lines of text; your only option is the whole thing, because it's all
one element.  (You can use the "a string is an array of characters" trick
to get substrings of that one element, e.g. *${aaa[1][2,4]}* is "abc".  But
again, the inner array is of *characters**, *not lines.)

Then you do this, using another transformation: the *f* expansion flag:

ccc=( ${(@f)aaa} )


By not putting double quotes around the expansion of aaa, you are throwing
away all the blank lines in its expansion. Since this is followed by a
version using the quotes, I assume that's intentional. But as far as I can
tell, the lack of quotation marks also removes any point for including the
*@* flag, since that flag's job is to maintain the identity of the separate
elements of an array when the expansion is quoted.  If it does anything at
all when not quoted, I'm unaware of it, but I admit that I could just be
ignorant of some subtlety.

ddd=( *"*${(@f)aaa}*"* )


Now you're keeping the blank lines, so the (f) gives you a separate array
element for every line that you get from the expansion - 8 of them, the
same as the output of *print -l $aaa | wc -l*.


redline *'\nddd=( "${(@f)aaa}" ) ... it seems like a lot of trouble to copy
the array as it is.'*


That comment confuses me; you aren't copying the array as it is at all!
You've gone from *aaa, *which has one element, to *ddd *having 8 elements.
That's a far cry from "copying as it is".

Your next comment says "8 not 6". I assume the expected 6 would be the
middle lines, without the leading and trailing blank ones, but I know of no
expansion that will produce that. You can get 6 elements out of *aaa*, like
this:

*eee=( $=aaa )*


But it gets there by throwing away all space, including newlines.  So the
six elements will be simply "abc", "def", "ghi", "jkl", "mno", and "pqr"


On Sat, Apr 13, 2024 at 11:14 AM Ray Andrews <rayandrews@eastlink.ca> wrote:

> I dunno.  I've lost the example that I saved. Never mind, I'll keep an eye on it, and figure out next time. Red herring for now.  It's a bit confusing looking into typeset -p output. All this 'splitting' stuff is not simple. For now everything works and I'm quite sure it's a bit more orthodox.
>
>
>
> A script:
>
> ---------------------------------------------------------------------------------
>
> redline () { echo -e "$red$@$nrm" }
>
> typeset -ga aaa=("
> abc
>
>     def ghi
>     jkl mno
>
>     pqr
> ")
>
> redline "\naaa:"
> print -l $aaa
> redline "\naaa[1]:"
> print -l $aaa[1]
> redline "linecount of aaa is: $#aaa ... Single element!"
>
> ccc=( ${(@f)aaa} )
>
> redline '\nccc=( ${(@f)aaa} )'
> print -l $ccc
> redline "linecount of ccc is: $#ccc ... split, but blank lines gone."
>
> ddd=( "${(@f)aaa}" )
>
> redline '\nddd=( "${(@f)aaa}" ) ... it seems like a lot of trouble to copy
> the array as it is.'
> print -l "$ddd[@]"  #... don't forget the quotes, idiot!"
> redline "linecount of ddd is: $#ddd ... split, but blanks preserved and
> counted. NB EIGHT NOT SIX!"
>
> redline "\nddd[1]: That's right it's blank, just as it should be."
> print -l $ddd[1]
> redline "\nddd[2]:"
> print -l $ddd[2]
>
> redline "And now the typesets\n"
> typeset -p aaa
> typeset -p ccc
> typeset -p ddd
>
> # Verbatim:
>
> # typeset -a aaa=( $'\nabc\n\n\tdef ghi\n\tjkl mno\n\n\tpqr\n' )
> # typeset -a ccc=( abc $'\tdef ghi' $'\tjkl mno' $'\tpqr' )
> # typeset -a ddd=( '' abc '' $'\tdef ghi' $'\tjkl mno' '' $'\tpqr' '' )
>
> # Aligned: Note the steeenking dollars ;-) ... and how they seem to
> replace the newlines. No?
>
> # typeset -a aaa=( $'\nabc  \n\n\tdef ghi  \n\tjkl mno   \n\n\tpqr\n'
> )     #Original with blanks
> # typeset -a ccc=(     abc    $'\tdef ghi' $'\tjkl mno   ' $'\tpqr' )
>          #No blanks.
> # typeset -a ddd=(  '' abc '' $'\tdef ghi' $'\tjkl mno' '' $'\tpqr' ''
> )    #Blanks retained BUT not the same structure!
>
>
> -----------------------------------------------------------------------------------
>
> ... so what about the dollars?
>
> 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.  Single quotes indicate elements.  And, best of all,
> copying an array, blanks and all, (not shown above) turns out to be simple:
>
> eee=( $aaa ) and:
>
> eee=( "{$(@f)aaa}" )
>
> ... turns out to be a false equivalence where newlines are REMOVED.  Don't
> be fooled by 'printf' -- it might not show you the genuine state of the
> array.  Scalars show their blank lines automatically but we need:
>
> print -l -- "$eee[@]"
>
> ... with arrays.  Trust typedef -p.
>
>
>

-- 
Mark J. Reed <markjreed@gmail.com>

[-- Attachment #2: Type: text/html, Size: 17714 bytes --]

  reply	other threads:[~2024-04-13 17:20 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-11  0:56 Ray Andrews
2024-04-12  4:55 ` Lawrence Velázquez
2024-04-12 14:48   ` Ray Andrews
2024-04-12 19:09     ` Bart Schaefer
2024-04-13  1:13       ` Ray Andrews
2024-04-13  1:33         ` Mark J. Reed
2024-04-13  2:28           ` Ray Andrews
2024-04-13  3:25             ` Lawrence Velázquez
2024-04-13 14:37               ` Ray Andrews
2024-04-13 15:14                 ` Ray Andrews
2024-04-13 17:19                   ` Mark J. Reed [this message]
2024-04-13 17:27                     ` Mark J. Reed
2024-04-13 18:08                       ` Ray Andrews
2024-04-13 19:45                         ` Bart Schaefer
2024-04-13 20:36                           ` Ray Andrews
2024-04-13 21:01                             ` Bart Schaefer
2024-04-14  0:28                               ` Ray Andrews
2024-04-14  0:30                               ` Lawrence Velázquez
2024-04-14  3:26                                 ` Ray Andrews
2024-04-14  3:49                                   ` Lawrence Velázquez
2024-04-14  4:57                                     ` Bart Schaefer
2024-04-14 13:24                                       ` Ray Andrews
2024-04-14 13:35                                         ` Roman Perepelitsa
2024-04-14 14:06                                           ` Ray Andrews
2024-04-14 14:15                                             ` Roman Perepelitsa
2024-04-14 14:53                                               ` Ray Andrews
2024-04-14 15:11                                                 ` Mark J. Reed
2024-04-14 16:23                                                   ` Ray Andrews
2024-04-14 14:06                                         ` Mark J. Reed
2024-04-14 14:47                                           ` Ray Andrews
2024-04-14 14:59                                             ` Mark J. Reed
2024-04-14 15:51                                         ` Bart Schaefer
2024-04-14 17:22                                           ` Ray Andrews
2024-04-14 17:42                                             ` Mark J. Reed
2024-04-14 18:24                                               ` Bart Schaefer
2024-04-14 22:00                                               ` Ray Andrews
2024-04-13 20:11                         ` Mark J. Reed
2024-04-13 20:53                   ` Bart Schaefer
2024-04-14  0:19                     ` Ray Andrews
2024-04-13  1:35         ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAA=-s3wwLUMexvh4aiOmLSWs4T2HE+80AFE63f50ffMTPprppQ@mail.gmail.com' \
    --to=markjreed@gmail.com \
    --cc=zsh-users@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).