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 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