9

I am making a bash script and I have encountered a problem. So let's say I got this

function create_some_array(){
  for i in 0 1 2 3 .. 10
  do
    a[i]=$i
  done
}

create_some_array
echo ${a[*]}

Is there any way I can make this work? I have searched quite a lot and nothing I found worked. I think making the a[] a global variable should work but I can't find something that actually works in my code. Is there any way to return the array from the function to main program?

Thanks in advance

codeforester
  • 39,467
  • 16
  • 112
  • 140
KayKo
  • 89
  • 1
  • 1
  • 2
  • 1
    This code works without any problems. Do not invent code to show the problem. Show us actual code that is causing the problem. –  Feb 12 '13 at 18:30
  • Welcome to Stack Overflow. Please improve your question by posting all **relevant** error messages exactly as they appear. Also, make sure to include a properly-formatted sample of your **expected output** so folks understand the results you're trying to achieve. – Todd A. Jacobs Feb 12 '13 at 18:32
  • @depesz: I half-agree. I think the asker *should* "invent code to show the problem" -- but (s)he has to make sure that it is (as you put it) "actual code that is causing the problem". This is known as an [SSCCE -- a short, self-contained, correct (compilable) example](http://sscce.org/). – ruakh Feb 12 '13 at 18:37
  • @ruakh: well, he/she **has** the code that is causing the problem. It's just that his invented version for showing it - doesn't contain problems. Unfortunately it's very common (at least on IRC) that people have problem with something, but show something different. –  Feb 12 '13 at 18:39
  • http://pastebin.com/2QcWfUNE It is going to expire in 1h – KayKo Feb 12 '13 at 18:44
  • the last 10 lines of my code won't work – KayKo Feb 12 '13 at 18:45
  • 1
    "won't work" is not a technical description. Try running your script with `bash -x script_name` which will trace what is happening. – cdarke Feb 12 '13 at 18:52
  • bah damn! thanks cdarke! Well there was an exit 0 that was shutting down my programm before displaying my arrays! I commented it out and it worked!! Thanks :) – KayKo Feb 12 '13 at 18:56
  • `mkdir tmp; touch tmp/{file1,file2}; ln tmp/file2 tmp/file3; bash yourscript tmp` outputs "The index number of .../tmp/file2 is 28578767 and its hard link is 2", "file2 is hardlinked to file3 with indexnumber: 28578767, file3 is hardlinked to file2 with indexnumber: 28578767". Seems to be working fine. – that other guy Feb 12 '13 at 18:56
  • @depesz: Right, but do you really want every question-asker to post the entire program that they have a problem with? It's better for them to narrow down the problem, and post a small-but-complete program that demonstrates the problem. This asker missed the "that demonstrates the problem" part; you want to go too far in the other direction, by missing the "small" part. – ruakh Feb 12 '13 at 18:58
  • It worked fine now, as I said program was shutting down before it reads the last 10± lines that's why I couldn't get the the desired output! Thanks you all for your help! – KayKo Feb 12 '13 at 19:02
  • @ruakh: I do not want to see whole program. But if I have to choose, I choose too much information vs. too small, and misleading. –  Feb 12 '13 at 19:21

5 Answers5

4

This won't work as expected when there are whitespaces in the arrays:

function create_some_array() {
    local -a a=()
    for i in $(seq $1 $2); do
        a[i]="$i $[$i*$i]"
    done
    echo ${a[@]}
}

and worse: if you try to get array indices from the outside "a", it turns out to be a scalar:

echo ${!a[@]}

even assignment as an array wont help, as possible quoting is naturally removed by the echo line and evaluation order cannot be manipulated to escape quoting: try

function create_some_array() {
...
    echo "${a[@]}"
}

a=($(create_some_array 0 10))
echo ${!a[@]}

Still, printf seems not to help either:

function create_some_array() {
...
    printf " \"%s\"" "${a[@]}"
}

seems to produce correct output on one hand:

$ create_some_array 0 3; echo
 "0 0" "1 1" "2 4" "3 9"

but assignment doesn't work on the other:

$ b=($(create_some_array 0 3))
$ echo ${!b[@]}
0 1 2 3 4 5 6 7

So my last trick was to do assignment as follows:

$ eval b=("$(create_some_array 0 3)")
$ echo -e "${!b[@]}\n${b[3]}"
0 1 2 3
3 9

Tataaa!

P.S.: printf "%q " "${a[@]}" also works fine...

Hans
  • 41
  • 2
  • annoying! this works but my IDE is given me an error that it wont suppress ... parsing stopped here. Invalid use of parantheses? .. annoying but +1 – danday74 May 20 '21 at 15:00
3

This works fine as described. The most likely reason it doesn't work in your actual code is because you happen to run it in a subshell:

cat textfile | create_some_array
echo ${a[*]}

would not work, because each element in a pipeline runs in a subshell, and

myvalue=$(create_some_array)
echo ${a[*]}

would not work, since command expansion happens in a subshell.

that other guy
  • 116,971
  • 11
  • 170
  • 194
  • j=`ls -i "$i" | awk '{print $1}'`; inode[count]=$j; This is the part i insert into an array. And when I try to echo this outside the function it dosnt work – KayKo Feb 12 '13 at 18:33
2

You can make an array local to a function, and then return it:

function create_some_array(){
    local -a a=()
    for i in $(seq $1 $2); do
        a[i]=$i
    done
    echo ${a[@]}
}

declare -a a=()

a=$(create_some_array 0 10)

for i in ${a[@]}; do
   echo "i = " $i
done
didierc
  • 14,572
  • 3
  • 32
  • 52
2

Hi here is my solution:

show(){
    local array=()
    array+=("hi")
    array+=("everything")
    array+=("well?")
    echo "${array[@]}"
}

for e in $(show);do
    echo $e
done

Try this code on: https://www.tutorialspoint.com/execute_bash_online.php

  • 1
    this works +1 but its kinda annoying coz if u dump the length of the array it is always 1 - my IDE warns me its converted it to a string and the console output agrees – danday74 May 20 '21 at 14:50
0

Both these work for me with sh and bash:

arr1=("192.168.3.4" "192.168.3.4" "192.168.3.3")

strArr=$(removeDupes arr1) # strArr is a string
for item in $strArr; do arr2+=("$item"); done # convert it to an array
len2=${#arr2[@]} # get array length
echo "${len2}" # echo length

eval arr3=("$(removeDupes arr1)") # shellcheck does not like this line and won't suppress it but it works
len3=${#arr3[@]} # get array length
echo "${len3}" # echo length

As an aside, the removeDupes function looks like this:

removeDupes() {
  arg="$1[@]"
  arr=("${!arg}")
  len=${#arr[@]}
  resultArr=()
  # some array manipulation here
  echo "${resultArr[@]}"
}

This answer is based on but better explains and simplifies the answers from @Hans and @didierc

danday74
  • 52,471
  • 49
  • 232
  • 283