-1

I have a bash script like:

#!/bin/bash

tom[0]="28 years old, computer science bs"
tom[1]="41 years old, physics bs"

ryan[0]="32 years old, technician"

mary[0]="25 years old, math bs"
mary[1]="30 years old, chemistry ba"

robert[0]="34 years old, math bs"

for name in robert mary tom ryan  
do  
    echo "name = ${name}:" 
    for who in "${name[@]}"
    do  
        echo "age,degree = ${!name}"  
    done
done

exit 0

output:

name = robert:
age,degree = 34 years old, math bs
name = mary:
age,degree = 25 years old, math bs
name = tom:
age,degree = 28 years old, computer science bs
name = ryan:
age,degree = 32 years old, technician

How do I modify my bash script to display below output:

name = robert:
age,degree = 34 years old, math bs

name = mary:
age,degree = 25 years old, math bs
age,degree = 30 years old, chemistry ba

name = tom:
age,degree = 28 years old, computer science bs
age,degree = 41 years old, physics bs

name = ryan:
age,degree = 32 years old, technician

novi2023
  • 1
  • 3
  • 4
    It's not clear what you mean. Just do `echo mary` or `echo tom`. – Barmar May 30 '23 at 20:00
  • 1
    It seems like you probably want an associative array, not multiple array variables. `info['tom0']="28 years old, computer science bs"; info['mary0']="25 years old, math bs"; info[mary1]="30 years old, chemistry ba";` – Barmar May 30 '23 at 20:04
  • 2
    Unfortunately, bash doesn't have 2-dimensional arrays. It's probably not the best language to use for an application like this. – Barmar May 30 '23 at 20:06
  • I was trying to make the problem I'm trying to solve simple by provided those arrays. Those arrays are given and I can't re-name or re-arrange them. I have about a hundred of arrays like that. – novi2023 May 30 '23 at 20:15
  • 1
    What problem are you trying to solve? `echo tom; printf '%s\n' "${tom[@]}"` – Barmar May 30 '23 at 20:24
  • 1
    Are you looking for indirect variables? See https://stackoverflow.com/questions/12691121/bash-array-expansion-using-variable-indirection-expansion – Barmar May 30 '23 at 20:25
  • If you have about 100 arrays, the chances are very high that you shouldn't be doing whatever you're doing using bash or any other shell. – Ed Morton May 30 '23 at 20:48
  • I need to loop through them in order, like for i in "${tom[@]}" "${mary[@]}" ... "$trevor[@]}", and print contents in them, how do I print "tom", "mary" ... "trevor" before their contents? – novi2023 May 30 '23 at 20:54
  • 3
    It sounds very much like you have the wrong approach to whatever you're trying to do. If you ask a question about THAT, including a [mcve] with concise, testable sample input, expected output, and code, then we can help you better than showing you how to keep going down your current path. – Ed Morton May 30 '23 at 20:56
  • I suspect it's along those lines: `for name in tom mary robert; do array="$name[@]"; echo "$name: ${!array}"; done` – Cyrus May 30 '23 at 21:06
  • 1
    Thanks @Cyrus. Your solution worked for my problem. My problem is more complex, I just tried to simplify it, but I think I accidentally made it confused. I'm glad that you got what I meant. Thank you. – novi2023 May 30 '23 at 21:41
  • 2
    @novi2023 we all understood what you wanted to do, it wasn't confusing, but we wanted to help you come up with a better approach as you seemed to be asking an [XY Question](https://mywiki.wooledge.org/XyProblem). – Ed Morton May 30 '23 at 22:23
  • one small problem is if I use array="$name[@]", it will have all items/elements assigned to array, how do I separate them? I need name[0] to be separated from name[1], like that... – novi2023 May 30 '23 at 22:40
  • See [How to iterate over an array using indirect reference?](https://stackoverflow.com/q/11180714/4154375), but note that the accepted answer has multiple bugs. See [Why should eval be avoided in Bash, and what should I use instead?](https://stackoverflow.com/q/17529220/4154375) if you consider using `eval`. Also see [BashFAQ/006 (How can I use variable variables (indirect variables, pointers, references) or associative arrays?)](https://mywiki.wooledge.org/BashFAQ/006). – pjh May 30 '23 at 22:59
  • I need to use bash, because I need the commands to be executed fast... I have re-worded my problem, used @Cyrus solution partially. – novi2023 May 30 '23 at 23:22
  • Very hard to figure out what you want exactly. In the new output, mary's data is all on 1 line, tom's data is on two lines. Make sure you show us EXACTLY what you want in the question, and double check your question to ensure you displayed it like you require. – Nic3500 May 31 '23 at 02:59
  • Oh, I didn't mean mary's data are on same line. I like to print all elements of each array on a separate line. I'm not familiar with this website format yet, I couldn't get the 2nd element in mary's array to the next line. – novi2023 May 31 '23 at 03:30

1 Answers1

0

Bash arrays are tricky. While "${!name}" gives you access to a scalar variable by name (or to an array’s zeroth element), you cannot access array elements other than [0] directly this way. For example, the construct "${!name[@]}" would expand to the array’s indices rather than to the stored values.

BTW, "${name[@]}" makes little sense in your code; it is equivalent to "$name" in this special case, because a scalar string "$name" is also (implicitly) "${name[0]}" which (in absence of other array elements) equals "${name[@]}".

To access Bash arrays by name, you need almost-pointers in the form of declare -n. That gives you an alias which behaves (almost) like the referenced variable (array in this case):

tom=('28 years old, computer science bs'
     '41 years old, physics bs')
ryan=('32 years old, technician')
mary=('25 years old, math bs'
      '30 years old, chemistry ba')
robert=('34 years old, math bs')

for name in robert mary tom ryan; do
  printf '\nname = %s:\n' "$name"
  declare -n array="$name"
  printf '%s\n' "${array[@]}"
done

In the snippet above one could also loop over "${array[@]}" using a for-loop, but one can just as well let printf handle a few extra arguments.

Andrej Podzimek
  • 2,409
  • 9
  • 12
  • Thank you @Andrej for spending time to explain the differences of how to access the bash arrays. I appreciate it. I can use your solutions, I just have to re-arrange the data ( index arrays) passed down to me. I still would prefer not to alter the original data, but if I can't find any other way, then I will re-arrange those given data. – novi2023 May 31 '23 at 20:06
  • Your solutions actually worked. After I played around with it, I didn't have to modify any of the arrays given at all. I used for loop and it actually displayed what I was trying to accomplish. Thanks a lot. – novi2023 May 31 '23 at 22:26