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
  • 3
    Don't use sed for this, you'll end up with a parsing corner case nightmare. – Chris Down Oct 6 '13 at 6:34

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.

  • 1
    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

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

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.