Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I am trying to pass a array into a function and whatever changes made to the array is reflected outside the function

function update_array()
{   
    ${1[0]}="abc" # trying to change zero-index array to "abc" , 
                  #  bad substitution error


}

foo=(foo bar)

update_array foo[@]

for i in ${foo[@]}
    do
       echo "$i" # currently changes are not reflected outside the function

    done

My questions are

1) How do i access the index array eg: zero index array , in the function , what is the syntax for it

2) How do i make changes to this index array so that the changes are reflected outsite the function also

share|improve this question
add comment

4 Answers 4

Probably your best bet is

function update_array { eval "${1}[0]=abc"; }

foo=(a b c)
echo ${foo[@]}

update_array foo
echo ${foo[@]}
a b c
abc b c
share|improve this answer
    
Use of eval is possibly dangerous. If someone were to run update_array 'echo hi;_', hi would be echoed. If echo hi was something malicious, harm could be done. Just a warning :-) –  minerz029 Jan 10 at 5:21
add comment

Several problems, in logical order of fixing:

  • Style (pet peeve)
  • With your ${...} statement in update_array(), the ${..} syntax to use a variable, not define it.

    Example:

    foo[0]=abc  # assigns 'abc' to foo[0]
    
  • Working around that the array name is stored in a variable.

    Not working:

    $1[0]=abc
    

    Working:

    declare -g "$1[0]=abc"  # -g arg is for a global variable
    
  • Passing an argument to update_array() should pass the variable name (foo in this case), not the contents of the array. foo[@] is nothing special, it is a completely normal string (in Bash).

  • Variable expansion with ${foo[@]} should be double-quoted.

Working version of the code is below:

update_array() {   
    declare -g "$1[0]=abc"
}

foo=(foo bar)

update_array foo

for i in "${foo[@]}"; do
    echo "$i"
done

## Following line added by me for further clarification
declare -p foo

which prints, correctly:

abc
bar
declare -a foo='([0]="abc" [1]="bar")'
share|improve this answer
    
that declaration's been confusing me.. shouldn't a declaration of variable precede the definition.. –  rusty Jan 10 at 5:40
    
@hash declare is a bash builtin command (help declare). It is basically the same as variable assignment, declare -g "$1[0]=abc" is saying 'declare zero index of $1 to be abc' (equiv. to (in theory) $1[0]=abc) –  minerz029 Jan 10 at 5:42
    
got that.. this link suggests, "...declare/typeset are very weak form of the typing..." and may be I'll be using those only if I need to typecast my variables or other extra control.. –  rusty Jan 10 at 6:03
add comment

Declaration of variables might not be necessary in Bash.1 Yes you can use declare/typeset for more control over your bash variables. So I reckon you don't have to create a function just for the purpose of declaring a new array.

This script below demonstrates a direct defining of array:

#!/bin/bash
function define_array_elements() {
# You can note the array elements being defined directly, without a prior 
# definition of the variable.
for i in {1..10}; do
    var_name[$i]="Field $i of the list"
done
}

define_array_elements > /dev/null

for i in {1..10}; do
    echo "Field $i is: ${var_name[$i]}"
done

(An example borrowed from How to declare an array but not define it? with just a little modification.)

share|improve this answer
add comment

Short answer is: you cannot. Bash does not have a way to pass variables by reference, so there's no generic way of doing it; you're left with (ugly) hacks including indirection and/or eval.

The upcoming bash 4.3 will introduce nameref variables, which allow you to pass variables by reference, but even this feature falls short since you still risk name collition.

# example of passing variables by reference in bash 4.3
update_array() {
    declare -n array=$1
    array[0]=abc
}

foo=( foo bar )

update_array foo

printf '<%s>\n' "${foo[@]}" # outputs <abc> and <bar>

In that example, if the array was named array instead of foo, it would fail since declare -n array=array is an error (declare: array: nameref variable self references not allowed).

See http://mywiki.wooledge.org/BashFAQ/006 for other hacks.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.