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).
Function parameters are local to the function.
awk '
function foo(x,y) {y=x*x; print "y in function: "y}
BEGIN {foo(2); print "y out of function: " y}
'
y in function: 4
y out of function:
If you pass fewer values to a function than there are parameters, the extra parameters are just empty. You might sometimes see functions defined like
function foo(a, b, c d, e, f) {...
where the parameters after the whitespace are local variables and are not intended to take a value at invocation.
No reason why this can't work for local arrays:
awk '
function bar(x) {
split("hello world", x)
print "in: " x[1]
}
BEGIN {
x[1]="world"
bar()
print "out: " x[1]}
'
in: hello
out: world
Best Answer
zsh
'sreturn
builtin can only return a 32bit signed integer like the_exit()
system call. While that's better than most other Bourne-like shells, that still can't return arbitrary strings or list of strings like therc
/es
shells. The return status is more about returning a success/failure indication.Here, alternatively, you can have the function take the name of the array to fill in as argument, like:
Your
printf '%s\0'
approach wouldn't work for array elements that contain NULs.Instead you could use the
qq
parameter expansion flag to quote elements on output, and thez
(to parse quotes) andQ
(to remove quoting) on input like:But in addition to being less legible, it's also less efficient as it means forking a process and transfering the output of
myfunc
through a pipe in addition to the quoting/unquoting.