0

I'm tasked with updating my script with arrays so it will run multiple domains. Thing is, I'm not well versed in loop arrays. I have done some searching online and I'm not fully understanding how to add the arrays to what I already have here. That is what doesn't make sense to me. I understand (I think) how the array works but when I try to implement arrays I get mass errors. Any advice/tips would be helpful.

Currently this code works perfectly. But only with a single domain at at time.

Looking for advice on best options, even if Arrays aren't it.

#distribution.sh
#Gathers info and creates the .json file needed to create distribution information for AWS domain sites

#Gather web-id and assign it to the variable "webid"
echo "Insert the webid for the site you are working with:"
read webid

#Gather sub domain info (www) for the site in question and assign it to the variable "subdomain"
echo "Insert the sub domain name for the site you are working with:"
read subdomain      

#Gather domain info (domain.com) for the site in question and assign it to the variable "domain"
echo "Insert the domain name for the site you are working with:"
read domain

#Check spelling with the user
printf "Your WebID is: $webid\nYour sub domain is: $subdomain\nYour domain 
is: $domain\n"
read -p "Is this correct? y/n " -n 1 -r
echo #
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
    exit 1
else
    printf "{\n  \"web_ids\": [\n    {\n      \"web_id\": \"$webid\",\n      
    \"domains\": {\n        \"$domain\": {\n          \"vhosts\": [\n            
    \"$domain\",\n            \"$subdomain.$domain\"\n          ]\n        }\n      
    }\n    }\n  ]\n}\n\n" > $domain.json

    #Run create-distribution on our newly created .json file
    create-distribution $domain.json

    #Display the arn line from the .json file after the fact so we can copy it into case notes per process
    cat $domain.json | grep dist
fi
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Lex Leach
  • 17
  • 6
  • Welcome to SO. Please reduce your code to the problem at hand, provide a [mcve] – mbuechmann Sep 19 '18 at 06:27
  • There ya go, thats about as minimal as I can get for it to be complete. Thanks. – Lex Leach Sep 19 '18 at 06:41
  • As an aside, your original script looks like it has a lot of code duplication. You should look into defining functions you can reuse so there is no duplication. Google "dry principle". – tripleee Sep 19 '18 at 08:44

1 Answers1

1

Here is a brief refactoring which avoids the pesky interactive input with read and removes some common shell antipatterns, as well as fixes the lack of indentation. I have replaced your comments with inline comments which document the refactoring in more detail.

This simply loops over a here document, so there are no arrays here.

#!/bin/sh
# Read input data from a here document
while read -r webid subdomain domain; do
    # use printf the way $dmr intended
    # print diagnostics to stderr
    printf "%s: Your WebID is: %s\nYour sub domain is: %s\nYour domain is: %s\n" "$0" "$webid" "$subdomain" "$domain" >&2
    # use single quotes to reduce backslashitis in format string
    printf '{\n  "web_ids": [\n    {\n      "web_id": "%s",\n              "domains": {\n        "%s": {\n          "vhosts": [\n                    "%s",\n            "%s.%s"\n          ]\n        }\n              }\n    }\n  ]\n}\n\n' "$webid" "$domain" "$domain" "$subdomain" "$domain" > "$domain".json
    # maybe this could read stdin to avoid temp file?
    create-distribution "$domain".json
    # avoid useless use of cat
    grep dist "$domain".json
    # you should probably use a proper JSON tool like jq though
    #jq -c .dist "$domain".json
done <<\____
    firstwebid   its-subdomain         itsdomain
    secondwebid  subdomain-for-second  domainforsecond
____

The here dooument is the text between \____ and ____; each line in the document supplies values for one iteration of the while ... done loop to populate the three variables in the read statement.

Arrays are not a particularly good fit here because you have a matrix in two dimensions. You could loop over synchronized indices, but that seems to me like a complication.

webids=(first second third)
domains=(one two three)
subdomains=(one other different)
for ((i=0; i<${#webids[@]}; ++i)); do
    printf '...' "${webids[i]}" "${domains[i]}" "${subdomains[i]}"
done

As you can see, this kind of works as long as you have very small arrays, but it gets really pesky once you get more than about half a dozen items in each array -- keeping them in sync so that the 21st item in the first array corresponds to the 21st item in the other two becomes a significant chore unto itself, which is easily avoidable if you keep each entry in one place like in the here document.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • The "human-readable" JSON is not really useful, nor really human-readable here. If you want the JSON file to be properly human-readable, maybe run it through `jq .` to have it formatted for you. This could simplify your `printf` format string significantly. – tripleee Sep 19 '18 at 08:47
  • Thank you, this helps a lot. Questions, what is the purpose of done `<<\____ firstwebid its-subdomain itsdomain secondwebid subdomain-for-second domainforsecond ____` – Lex Leach Sep 19 '18 at 18:57
  • That's a [here document](https://en.wikipedia.org/wiki/Here_document) containing example data for two iterations of the loop. The first iteration gets `firstwebid` as the `webid`, `its-subdomain` as the `subdomain` parameter, and `itsdomain` as `domain`. See updated answer now. – tripleee Sep 19 '18 at 19:12
  • is it possible to use an if statement or something to check for something in a json file? Example below ' if [ "dist" exists in "$domain.json" ]; then echo "$domain ARN ID" cat $domain.json | grep dist else echo "$domain ARN ID" echo "No Domain present or Domain Distribution already exists. See Dump file for ARN ID." fi' – Lex Leach Sep 20 '18 at 21:27
  • `if arn=$(grep "$dist" "$domain.json"); then echo "$domain ARN ID $arn"; else ...` – tripleee Sep 21 '18 at 06:06
  • You could also refactor that with Awk or `sed` to basically transform the JSON file into either a message that the ARN ID was found or else the error message; I'm not particularly fond of capturing things into shell variables. And again, `jq` would seem like a more suitable tool for this. (Or maybe the `create-distribution` tool could be refactored to indicate whether it ran successfully or not. Perhaps it already does that -- have you examined its result code?) – tripleee Sep 21 '18 at 06:08
  • You can post code in backticks in comments but the formatting facilities are more limited than in a question. If you still can't figure it out, maybe post a new question; it might be a good idea to link back to this one (the question's title at the top of the page is a [link to the current question](https://stackoverflow.com/questions/52399293/how-can-i-generalize-this-to-loop-over-multiple-inputs-bash-arrays) or you can copy/paste from your browser's location bar). – tripleee Sep 21 '18 at 06:10
  • So just to recap, perhaps `if create-distribution; then sed -n "s/$dist/$domain ARN id &/p"; else echo "$0: create-distribution failed for $domain" >&2; fi` – tripleee Sep 21 '18 at 06:12
  • Thank you for this, I'm not by any means good at this stuff, I'm just self taught from the web, but I'm curious what some of these statements mean. For instance, my if statement looks completely different from yours. Yours has things like `sed -n` `&/p;` `$0` and `>&;` . I think I know the meaning of some of them but I was wondering if you don't mind explaining them? I'm making notes of these things so I understand the use/meaning of them. – Lex Leach Sep 21 '18 at 15:14
  • `>&2` directs output to standard error. `&` in `sed` refers to the string which was matched by the regex in a `s/regex/replacement/` substitution. The `-n` option says to not print lines unless specifically requested and the `/p` option on a substitution says to print if a substitution took place. You can find most of these explained on Stack Overflow or via Google. You might also want to check https://symbolhound.com/ and https://explainshell.com/ – tripleee Sep 21 '18 at 15:29