TL, DR:
array_of_lines=("${(@f)$(my_command)}")
First mistake (→ Q2): IFS='\n'
sets IFS
to the two characters \
and n
. To set IFS
to a newline, use IFS=$'\n'
.
Second mistake: to set a variable to an array value, you need parentheses around the elements: array_of_lines=(foo bar)
.
This would work, except that it strips empty lines, because consecutive whitespace counts as a single separator:
IFS=$'\n' array_of_lines=($(my_command))
You can retain the empty lines except at the very end by doubling the whitespace character in IFS
:
IFS=$'\n\n' array_of_lines=($(my_command))
To keep trailing empty lines as well, you'd have to add something to the command's output, because this happens in the command substitution itself, not from parsing it.
IFS=$'\n\n' array_of_lines=($(my_command; echo .)); unset 'array_of_lines[-1]'
(assuming the output of my_command
doesn't end in a non-delimited line; also note that you lose the exit status of my_command
)
Note that all the snippets above leave IFS
with its non-default value, so they may mess up subsequent code. To keep the setting of IFS
local, put the whole thing into a function where you declare IFS
local (here also taking care of preserving the command's exit status):
collect_lines() {
local IFS=$'\n\n' ret
array_of_lines=($("$@"; ret=$?; echo .; exit $ret))
ret=$?
unset 'array_of_lines[-1]'
return $ret
}
collect_lines my_command
But I recommend not to mess with IFS
; instead, use the f
expansion flag to split on newlines (→ Q1):
array_of_lines=("${(@f)$(my_command)}")
Or to preserve trailing empty lines:
array_of_lines=("${(@f)$(my_command; echo .)}")
unset 'array_of_lines[-1]'
The value of IFS
doesn't matter there. I suspect that you used a command that splits on IFS
to print $array_of_lines
in your tests (→ Q3).
I think you are looking for :-
parameter substitution:
$ restofarglist='abc,def'
$ echo ${(s/,/)${:-arg1,arg2,$restofarglist}}
arg1 arg2 abc def
From man zsh:
${name:-word}
If name is set, or in the second form is non-null, then substitute its value;
otherwise substitute word. In the second form name may be omitted, in which
case word is always substituted.
Actually you can make this example a little bit shorter:
$ echo ${${:-arg1,arg2,$restofarglist}//,/ }
arg1 arg2 abc def
Best Answer
Use
$^array
.It turns the array into a sort of brace expansion of the array. As in when
a=(foo bar baz)
,$^a
would be a bit like{foo,bar,baz}
.For multiplexing arrays:
Naturally, if the prefix or suffix contain shell special characters (like
;
that separates commands or space that separate words, or$"'&*[?~
...), they must be quoted:same as for
csh
's (and bash, ksh, zsh's):$^a
itself must not be quoted,"foo${^a}bar"
would expand as one word. One case where you would want$^array
to be quoted, the same as for$array
is when you want to preserve empty elements. Then, you need to quote the array expansion and use the(@)
flag or the"${array[@]}"
syntax (reminiscent of the Bourne shell's"$@"
):