0

Im facing a problem with assigning a value to a variable that its name is stored in other variable or a file

cat ids.txt

ID1
ID2
ID3

What i want to do is:

for i in `cat ids.txt'; do $i=`cat /proc/sys/kernel/random/uuid`

or

for i in ID1 ID2 ID3; do $i=`cat /proc/sys/kernel/random/uuid`

But its not working. What i would like to have, its something like:

echo $ID1
5dcteeee-6abb-4agg-86bb-948593020451
echo $ID2
5dcteeee-6abb-4agg-46db-948593322990
echo $ID3
5dcteeee-6abb-4agg-86cb-948593abcd45

Pipiloski
  • 3
  • 1
  • 1
    Using dynamic variable names like this can be done, but it's messy; generally, arrays are a better way to handle groups of values. See ["Dynamic variable names in Bash"](https://stackoverflow.com/questions/16553089/dynamic-variable-names-in-bash) and [BashFAQ #6: "How can I use variable variables (indirect variables, pointers, references) or associative arrays?"](http://mywiki.wooledge.org/BashFAQ/006) – Gordon Davisson Nov 06 '22 at 20:22
  • You really want to overwrite your loop variable `i` with content from `/proc/sys/kernel/random/uuid`? – Cyrus Nov 06 '22 at 20:36

3 Answers3

0

Use declare. https://linuxcommand.org/lc3_man_pages/declareh.html

# declare values
for i in ID1 ID2 ID3; do
  declare ${i}=$(cat /proc/sys/kernel/random/uuid)
done

# read values (note the `!` in the variable to simulate "$ID1", not ID1)
for i in ID1 ID2 ID3; do echo ${!i}; done

3f204128-bac6-481e-abd3-37bb6cb522da
ccddd0fb-1b6c-492e-bda3-f976ca62d946
ff5e04b9-2e51-4dac-be41-4c56cfbce22e

Or better yet... Reading IDs from the file:

for i in $(cat ids.txt); do
  echo "ID from file: ${i}"
  declare ${i}=$(cat /proc/sys/kernel/random/uuid)
  echo "${i}=${!i}"
done

Result:

$ cat ids.txt
ID1
ID2
ID3

$ for i in $(cat ids.txt); do echo "ID from file: ${i}"; declare ${i}=$(cat /proc/sys/kernel/random/uuid); echo "${i}=${!i}"; done
ID from file: ID1
ID1=d5c4a002-9039-498b-930f-0aab488eb6da
ID from file: ID2
ID2=a77f6c01-7170-4f4f-a924-1069e48e93db
ID from file: ID3
ID3=bafe8bb2-98e6-40fa-9fb2-0bcfd4b69fad
TheAnalogyGuy
  • 376
  • 2
  • 9
  • Thank You so much, i was missing this "declare" – Pipiloski Nov 06 '22 at 20:49
  • Anytime! I ran into this one a while back. Glad to help and thanks for marking as the answer. Hopefully the community can provide any comments on whether this is a "good" method or not, but it worked for me! Also, `uuidgen` is a nice little shortcut to do the same thing you are doing with cat.. `uuidgen -h`. Good luck! – TheAnalogyGuy Nov 06 '22 at 20:53
0

A one-liner using . built-in, process and command substitution, and printf's implicit loop:

. <(printf '%s=$(cat /proc/sys/kernel/random/uuid)\n' $(<ids.txt))
echo "ID1=$ID1"; echo "ID2=$ID2"; echo "ID3=$ID3"

Note: The lines of ids.txt must consist of only valid variable names and the file must come from a trusted source. Checking that file by grep -vq '^[[:alpha:]][[:alnum:]]*$' ids.txt before calling this command may be a safer approach.

M. Nejat Aydin
  • 9,597
  • 1
  • 7
  • 17
0

Method with associative array:

#!/usr/bin/env bash

# Declares associative array to store ids and UUIDs
declare -A id_map=()

# Reads ids.txt into array
mapfile -t ids < ids.txt

# Iterates ids
for id in "${ids[@]}"; do
  # Populates id_map with uuid for each id
  # Prepends $id with an x because associative array keys must not be empty
  read -r id_map["x$id"] < /proc/sys/kernel/random/uuid
done

# Debug content of id_map
for x_id in "${!id_map[@]}"; do
  id="${x_id#?}" # Trims leading x filler
  printf '%s=%s\n' "$id" "${id_map[$x_id]}"
done
Léa Gris
  • 17,497
  • 4
  • 32
  • 41