0

I have a script like below, and I'd like for the script to loop through variables and create a file for each variable. I have researched and can't find a way to do it. Might be that my googling is subpar.

API="link to API"

#city
newyork="latitude-longitude"
boston="latitude-longitude"
miami="latitude-longitude

curl -s "$API$city" > $city.txt 

I have tried putting the variables in a different file and then making a loop for each line, but then the script of course included the name of the variable. Unsure of how to attack this issue without using an array.

Andy Lester
  • 91,102
  • 13
  • 100
  • 152
Arawelo
  • 33
  • 6
  • 2
    Why exactly do you want "to attack this issue without using an array" in the first place? What's wrong with `cities=([ny]="x1" [boston]="y2" [miami]="z3")`? – Andrey Tyukin Nov 14 '22 at 15:30
  • I'm not very familiar with arrays, and feel that if I use it there will be more issues later on. – Arawelo Nov 14 '22 at 15:40
  • 4
    Well, familiar or not, it's definitely going to be easier than messing with something like [indirect variable references](https://tldp.org/LDP/abs/html/ivr.html). – Andrey Tyukin Nov 14 '22 at 15:43
  • @Arawelo This post has examples of what you are trying to accomplish using various methods: https://unix.stackexchange.com/questions/459692/loop-through-variables. Consider reading in cities from a file so you don't have to edit the script every time the list changes, – Gary_W Nov 14 '22 at 15:56
  • `for city in "$newyork" "$boston" "$miami"; do ...; done` – Barmar Nov 14 '22 at 15:58
  • @AndreyTyukin Unless `ny`, `boston` and `miami` are integers, you have to use `declare -A` to get an associative array. Else they are converted to index 0. – Benjamin W. Nov 14 '22 at 15:58
  • 1
    Please, never, never... use eval – Arnaud Valmary Nov 14 '22 at 16:05

1 Answers1

2

Two solutions for input data: hash (solution by Andrey Tyukin) or file

Hash

#! /usr/bin/env bash

API="link to API"

# cities
declare -A CITIES_HASH=(
    ["newyork"]="latitude-longitude"
    ["boston"]="latitude-longitude"
    ["miami"]="latitude-longitude"
)

# "[@]" for all hash entries prefixed by "!" to obtains keys instead of values
for CITY in "${!CITIES_HASH[@]}"; do
    curl -s "$API${CITIES_HASH[$CITY]}" > "${CITY}.txt"
done

File

#! /usr/bin/env bash

API="link to API"

while read -r; do
    [[ -z "${REPLY}" ]] && continue
    CITY="${REPLY%%=*}"
    LAT_LONG="${REPLY#*=}"
    LAT_LONG="${LAT_LONG//\"/}"
    curl -s "$API$LAT_LONG" > "${CITY}.txt"
done <<<"$(cat latitude-longitude.txt; echo)"

Alternative with !

echo "Alternative"
#cities
newyork="ny-latitude-longitude"
boston="bo-latitude-longitude"
miami="mi-latitude-longitude"

for CITY in newyork boston miami; do
    echo curl -s "$API${!CITY}" ">" "${CITY}.txt"
done

No solution is better than other. It depends about your source. Of course, if you read files like /usr/share/zoneinfo/zone.tab, the second method may be the right (with adaptations).

Arnaud Valmary
  • 2,039
  • 9
  • 14
  • 2
    why `<<<"$(cat latitude-longitude.txt; echo)"` vs the much simpler ` – tjm3772 Nov 14 '22 at 16:20
  • Just for forcing a line feed at end of flow – Arnaud Valmary Nov 14 '22 at 16:36
  • It's unnecessary to add these `echo`, since trailing newlines are deleted in a command substitution: `Bash performs the expansion by executing command in a subshell environment and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.` [See the corresponding section in the Bash Reference Manual](https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Command-Substitution). – gniourf_gniourf Nov 14 '22 at 17:37