0

I'm attempting to write a function that writes arrays with a name that's passed in. Given the following bash function:

function writeToArray {
    local name="$1"
    echo "$name"
    declare -a "$name"
    ${name[0]}="does this work?"      
}

Running like this:

writeToArray $("test")

I get two errors:

bash: declare: `': not a valid identifier
=does this work?: command not found

I am expecting to be able to do this:

writeToArray $("test")
for item in "${test[@]}"; do
        echo "item"
        echo "$item"
done

This should print:

item
does this work?

How could I properly configure this to write the array (named test in the example, such that this array named test is readable outside the function)?

1
  • 1
    @EdMorton Updated, I'm aiming to create an array called "test" that contains the string "does this work?" as its first element.
    – Lee
    Commented Mar 8, 2023 at 15:44

1 Answer 1

3

You'd use a nameref for that:

writeToArray() {
    local -n writeToArray_name="$1"
    writeToArray_name[0]="does this work?"      
}

Testing:

bash-5.0$ test[123]=qwe
bash-5.0$ writeToArray test
bash-5.0$ typeset -p test
declare -a test=([0]="does this work?" [123]="qwe")

With older versions of bash which didn't have namerefs yet, you could use eval:

writeToArray() {
  eval "$1[0]='does this work?'"
}

When writeToArray is invoked with test as argument, eval is passed test[0]='does this work?' as argument, and that in turns is evaluated as code in the shell language where it assigns does this work? to the element of index 0 of the test array (also works for associative array; scalar variables are converted to arrays).

Note that $("test") is syntax to capture and expand the output of test command and split+glob it when in list context. test (aka [) produces no output when not passed any argument), so $("test") expands to the empty string and split+glob gives you nothing at all out of it.

Here, it's the name of your variable that you want to pass to writeToArray, so test, not its contents ("$test") nor the output of a command by the same name ("$(test)") let alone the output of a command by the same name subject to split+glob as with your $("test") attempt.

2
  • Great answer, I'd become confused over use of $(...). I also noted your answer worked for writeToArray "test" (with quotation marks).
    – Lee
    Commented Mar 8, 2023 at 16:06
  • 1
    @Lee, would also work with "writeToArray" 'te'"st". Quotes in shells are to prevent some characters to be treated specially (and double quotes also prevent split+glob which is why you almost always want quotes around variable expansions), but here none of the characters in writeToArray or test are special to the shell so quoting is not needed. The only special characters are space (used to delimit arguments to that command) and newline used to delimit that command. Commented Mar 8, 2023 at 16:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .