bash - return array from function and display contents

After some bash self study and experimenting, I am stuck with returning an array from a function, and for the life of me can't see my error.

In short, what this should/must do is by using a function have a function which reads in values/strings from a file, returning an array:

  • declare an array: clients
  • assign the function's return array to array clients
  • display array clients

It seems to me as if the function reads the whole file and not line by line, thus putting all strings into a single cell in the array, and I am not sure how to explicitly display clients[0] as this $(clients[0]) fails in bash code

If by an means I am doing something incorrectly, please point this out too or any suggestions on optimising this too

#!/bin/bash
readArray(){ local array=() local i=0; local j=0 while IFS= read -r LINE && [[ -n "$LINE" ]] ; do array[$((i++))]+=${LINE}; # Append line to the array ((j++)) done < "$1"; rtr=${array[@]}
}
string="/home/cybex/openvpntest/openvpn.log"
declare -a clients
#sed -i '/^$/d' $string
clients=$(readArray "$string")
echo "${clients[@]}"
echo -e "array not empty, displaying array contents\n"
for i in "${!clients[@]}"; do echo "$i: ${clients[$i]}"
done
echo -e "\nfinished displaying contents of array"

cat openvpn.log

something
anotherthing
anotherlineoftext
here is one more line
and lastly
one with
a few spaces
nice

UPDATEFor anyone wanting to see how I resolved this:

  • declare a "global" array with

    declare -a clients
  • while the function executes, add values DIRECTLY to the clients array

To display a single index position of an array, ref. last line of code

echo "${clients[0]}" or any other number >=0

Working code:

declare -a clients
readArray(){ local array=() local i=0; local j=0 while IFS= read -r LINE && [[ -n "$LINE" ]] ; do clients[$((i++))]+=${LINE}; # Append line to the array ((j++)) done < "$1";
}
string="/home/cybex/openvpntest/openvpn.log"
sed -i '/^$/d' $string
readArray "$string"
echo "${clients[@]}"
echo -e "array not empty, displaying array contents\n"
for i in "${!clients[@]}"; do echo "$i: ${clients[$i]}"
done
echo -e "\nfinished displaying contents of array"
echo "${clients[0]}"

3 Answers

Already answered here.

You should do a minimal search in google, because this was the first link returned for "bash return array"

Edit:

In bash, functions don't return values. They can return a status (the same as other programs).

So, if you want to return something, you should use global variables that are updated inside your function.

6

Discussion

If you have come to the point of wanting to return an array from a function, then you are probably aware that you can only return status codes. Boo! You say. :-)

What can we do with other data in a function that we want to use in another function / context?

  1. echo

Assuming stdout is set to the terminal, at least you can see the contents of a variable or something.

  1. Output Redirection: > or >>

Not ideal, but possible. :-) There are probably more things you can do, but let's stop here.

Discussion continued ...

Let us say we think option #1 above sounds promising. What usually happens? Something like this ...

function listToString ()
{ echo "$*"
}

Reference: Your UNIX: The Ultimate Guide, 2nd Edition, p. 387 (last para).

If I call doSomething, it might, say, send a string message to stdout. That output can be captured in two different ways.

  1. Backticks `doSomething`
  2. This thing: $(doSomthing)

If that is true, then you can save something you send to stdout in another context.

var1=`doSomething`

or

var1=$(doSomething)

In summary ....

Convert a list to a string. Echo the string. Capture the echoed string with command substitution (see above). Use read combined with a here string (<<<) to convert the string into an array. Use array at your leisure.

File: new_users

fsmith
jdoe

Let's say we wanted to add new users with a function we made called addAccounts that loops over username arguments. The order of march would be.

  1. Make file
  2. Read file
  3. Convert list to a string
  4. Convert the string to an array.

The code would be something like this

function listToString ()
{ echo "$*"
}
usersString=$(listToString $(cat new_users))
read -a users <<< $usersString
addAccounts "${users[@]}"

listToString may not work with all lines of input. Test it on your input.

The last line should resolve to:

addAccounts "fsmith" "jdoe"

Many people will not understand the line ...

read -a users <<< $usersString

... because they have never heard of a here string.

This solution does not pass an array from a function, but it does allow you to convert the output of a function to an array. Some are satisfied with converting a list to a string and calling it a day, but if you truly want to deal with an official bash array, the here sting above will do that for you.

This trick won't always work (When you have values with whitespaces, or you want to return values that depend on input values), but it usually does the work:

array_returning_func() { echo "cat dog tree"
}
declare -a arr="$(array_returning_func)"
for obj in ${arr[@]}; do echo "$obj"
done

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like