kamituel
kamituel

Reputation: 35960

Assign single variable to an array (in place)

Consider following code:

a=(1 2 3)
a='seven'

export a
declare -p a

The output (from declare) is:

declare -ax a='([0]="seven" [1]="2" [2]="3")'

So a is an array. Questions:

  1. How to change second line, so a will not be an array anymore, but a simple variable with the value seven? I'm looking for a one-liner, without unset etc.
  2. Assigning an variable to the array replaces only first element, not the whole array. Where is this behaviour specified?

Note: Bash v. 3.2.48 (OS X).

(I've answered this question today, which got me thinking on this problem, and I'm looking for a cleaner solution).


Edit: I'm looking for a:

a=(1 2 3)

/* One line here please :) */
unset a
a='seven'

export a
declare -p a

but without doing explicit unset. It matters in a special case when a is in fact a PATH variable (see this question).

Upvotes: 3

Views: 281

Answers (2)

konsolebox
konsolebox

Reputation: 75488

You could just use the first value:

a=${a[0]}

or

a=$a

Since in arrays, the default value for it if a subscript is not provided is its first element value.

If you want to export your variable, you need to keep it from being an array. You could save it on a variable first, unset and reset it like:

b=a; unset a; a=$b
export a

Or you could do one-liners:

{ unset a; IFS= read -r a; } <<< "$a"
export a

eval "unset a; IFS= read -r a" <<< "$a"
export a

Note: The latter uses eval which is dangerous when not used properly so you have to be careful using it.

Update: It seems that <<< "" appends a newline to the end of the value, so we can't use read -rd '' to include lines that separate it. However we could use process substitution:

{ unset a; IFS= read -rd '' a; } < <(echo -n "$a")
export a

Turns out that saving the value of the variable to another first, unsetting it and re-assigning it is still the best way.

Upvotes: 1

devnull
devnull

Reputation: 123508

You need to use unset.

The first quote from the manual (given below) would explain that upon saying:

a='seven'

when a was an array earlier is identical to saying:

a[0]='seven'

Quoting from the manual:

When assigning to indexed arrays, if the optional subscript is supplied, that index is assigned to; otherwise the index of the element assigned is the last index assigned to by the statement plus one. Indexing starts at zero.


The unset builtin is used to destroy arrays. unset name[subscript] destroys the array element at index subscript. Care must be taken to avoid unwanted side effects caused by filename expansion. unset name, where name is an array, removes the entire array. A subscript of ‘*’ or ‘@’ also removes the entire array.

Upvotes: 2

Related Questions