I can easily capture stdout from a function call (in subshell) to a variable with:
val="$(get_value)"
I can also modify variables (for instance, an array) in a shell by reference so to speak in the same shell with something like:
function array.delete_by_index {
local array_name="$1"
local key="$2"
unset "$array_name[$key]"
eval "$array_name=(\"\${$array_name[@]}\")"
}
array.delete_by_index "array1" 0
But what I'm struggling to figure out how to do is to do both at the same time, in a clean manner. An example of where I want this is popping a value from an array:
function array.pop {
local array_name="$1"
local last_index=$(( $(eval "echo \${#$array_name[@]}") - 1 ))
local tmp="$array_name[\"$last_index\"]"
echo "${!tmp}"
# Changes "$array_name" here, but not in caller since this is a sub shell
array.delete_by_index "$array_name" $last_index
}
val="$(array.pop "array1")"
It seems to me like all forms of capturing stdout to a variable require a subshell in bash, and using a sub shell will not allow me the ability to change a value by reference in the caller's context.
I'm wondering if anyone know a magical bashism to accomplish this? I do not particularly want a solution that uses any kind of file/fifo on the filesystem.
The 2nd answer in this question seems to suggest that this is possible in ksh
using val="${ cmd; }"
, as this construct apparently allows for capturing output, but without using sub shells. So yes, I could technically switch to ksh, but I'd like to know if this is possible in bash.