Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top
arr=(a b c d)
declare -A brr
for i in ${!arr[@]}
echo ${brr[@]}                             #0 1 2 3

Is there any way to reverse the values and key pairs using sed or any other command. I think I would have to just do some pattern change of text instead of using bash loops, perhaps something like.

brr=($(echo ${!arr[@]} | sed commands))

so that the new array becomes like brr=([a]=0 [b]=1 [c]=2 [d]=3) if I use brace expansion it can come up to this point:

arr=(a b c d)
declare -A brr
var=${var// /,}
brr=$(eval echo [{$var}]=)
echo $brr                              #[a]= [b]= [c]= [d]=

now I just need to add the keys 0,1,2,3

EDIT : I was able to do it but can I make it shorter and simpler especially the sed lines

arr=(a b c d)
declare -A Rev
var=${arr[@]}                    #var is equal to a b c d
var=${var// /,}                  #var is equal to a,b,c,d after adding , for space
brr=$(eval echo Rev[{$var}]=)    #brr equal to Rev[a]= Rev[b]= Rev[c]= Rev[d]=

#Rev[a]= Rev[b]= Rev[c]= Rev[d]=

r="$(echo $brr | 
sed 's/ /\n/g' | sed '/./=' | sed '/./N; s/\n//' | 
  sed 's/\(^[0-9]\{1,\}\)\(.*\)/\2$(echo \1 - 1 | bc)/' | tr '\n' ';' |
                                                          sed "s/\[/\[\'/g;s/\]/\'\]/g")"
#pipe the output of echo(Rev[a]= Rev[b]= Rev[c]= Rev[d]=) to sed
#convert space to newlines
#add line numbers
#put the line numbers adjacent to the values Rev[a],Rev[b],Rev[c],Rev[d] like
# 1rev[a]=
# 2Rev[b]=
# 3Rev[c]=
# 4Rev[d]=
#change 1Rev[a]= format to Rev[a]=1
#convert newlines to ; looking like Rev[a]=0;Rev[b]=1;Rev[c]=2;Rev[d]=3
#put quotes around the keys Rev['a']=0;Rev['b']=1;Rev['c']=2;Rev['d']=3

eval $r
echo ${Rev[@]}      #0 1 2 3
echo ${!Rev[@]}     #a b c d
share|improve this question
Don't use sed for this, you'll end up with a parsing corner case nightmare. – Chris Down Oct 6 '13 at 6:34
up vote 4 down vote accepted

I would heed @ChrisDown's advice and not try to do something clever here. I would create the for loop and reverse the keys with the values in the new array. It's only a few lines of code.

Anything you create in this manner is going to be more difficult for others to support down the road, and more difficult for you to remember/understand how it works when you revisit the code in the future.

share|improve this answer
Never mind that the shell expansion to generate the input to sed is using a bash loop internally anyway, so whatever reason you have for avoiding iterating over the array is lost, with the additional loss of having to fork() a new process for the sed on top of that. – dannysauer Oct 6 '13 at 19:20
arr=(a b c d)
set -- $(echo ${arr[@]} | tr ' ' '\n' | sed "s/.*/arr['&']=/")
eval echo $(seq 1 ${#arr[@]} | sed 's/\(.*\)/${\1}$(echo \1 -1 | bc)/') 


declare -A brr
arr=(a b c d)
eval "brr=($(eval echo $(sed 's/\([0-9]\)/[${arr[\1]}]=\1/g' <(echo ${!arr[@]}))))"
echo ${brr[@]}


#arr['a']=0 arr['b']=1 arr['c']=2 arr['d']=3
share|improve this answer

As others have said, I think sed would be a difficult solution.

The following loop could accomplish what you want:

arr=(a b c d)
for i in ${!arr[@]}; do
echo ${brr[@]}
#[a]=0 [b]=1 [c]=2 [d]=3
share|improve this answer

Your Answer


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.