Sibbs Gambling
Sibbs Gambling

Reputation: 20365

Bash -- compactly unpack elements from array?

Is there a more compact alternative to

arr=( 1 2 3 )
e1=${arr[0]}
e2=${arr[1]}
e3=${arr[2]}

?

Something like,

e1, e2, e3=${arr[@]}

Upvotes: 5

Views: 3395

Answers (2)

Charles Duffy
Charles Duffy

Reputation: 295679

Generally speaking, asking this question implies that you shouldn't be using an array for your data in the first place.

That said, the following function is reusable and correct -- with no caveats around which data it can and can't be used for:

array_to_vars() {
  declare -n _arr=$1
  local var
  for var; do
    shift || return
    printf -v "$var" %s "$1"
  done
}

...usable as:

# put first element of arr into e1, second into e2, third into e3
# disregard the rest
array_to_vars arr e1 e2 e3

It's not as short as one might like, but it's less likely to cause bugs as something that works only for data not containing a sigil.


Let's say you're populating it like so:

read -r -a arr < <(command-that-generates-a-list)

You could replace that with:

read -r e1 e2 e3

Or let's say it's:

arr=( )
while read -r line; do
  arr+=( "$line" )
done < <(command-that-generates-a-list)

You could that replace that with:

{ read -r e1; read -r e2; read -r e3; } < <(command-that-generates-a-list)

or with:

{ IFS=$'\n' read -r -d '' e1 e2 e3; } < <(command-that-generates-a-list && printf '\0')

Or let's say it's:

arr=(${string//,/ })

...in that case, it would be simpler and more correct (avoiding undesired behaviors like glob expansion -- see BashPitfalls #50) to use:

IFS=, read -r e1 e2 e3 <<<"$string"

Upvotes: 3

anubhava
anubhava

Reputation: 785691

If you don't have whitespaces in your array element then you can use read using default IFS value (whitespace) in shell:

arr=( 1 2 3 )

# unset IFS to default value it has been set earlier
unset IFS

# read content in 3 variables
read e1 e2 e3 <<< "${arr[*]}"

# examine the content of variables
declare -p e1 e2 e3
declare -- e1="1"
declare -- e2="2"
declare -- e3="3"

Upvotes: 1

Related Questions