I'm trying to iterate over a variable that might be either null
or an array of strings.
ZEIT_DEPLOYMENT_ALIASES=null
or ZEIT_DEPLOYMENT_ALIASES=['domain.sh]
I'm a beginner in bash, I read bash iterate file list, except when empty but I couldn't figure it out.
I tried two different approaches.
The values of ZEIT_DEPLOYMENT_ALIASES
actually comes from jq
library, which reads JSON.
ZEIT_DEPLOYMENT_ALIASES=$(cat now.$CUSTOMER_REF_TO_DEPLOY.staging.json | jq --raw-output '.alias')
Approach 1
ZEIT_DEPLOYMENT_ALIASES=['test.sh']
Check if there are no aliases configured
if [ -z "$ZEIT_DEPLOYMENT_ALIASES" ]
then
ZEIT_DEPLOYMENT_ALIASES_COUNT=${#ZEIT_DEPLOYMENT_ALIASES[@]}
echo "$ZEIT_DEPLOYMENT_ALIASES_COUNT alias(es) found. Aliasing them now..."
# For each alias configured, then alias it to the deployed domain
for DEPLOYMENT_ALIAS in "${ZEIT_DEPLOYMENT_ALIASES_COUNT[@]}"
do
echo "npx now alias "$ZEIT_DEPLOYMENT_URL $DEPLOYMENT_ALIAS
npx now alias $ZEIT_DEPLOYMENT_URL $DEPLOYMENT_ALIAS --token $ZEIT_TOKEN || echo "Aliasing failed for '$DEPLOYMENT_ALIAS', but the build will continue regardless."
done
else
# $ZEIT_DEPLOYMENT_ALIASES is null, this happens when it was not defined in the now.json file
echo "There are no more aliases to configure. You can add more aliases from your now.json 'alias' property. See https://vercel.com/docs/configuration?query=alias%20domain#project/alias"
echo "$ZEIT_DEPLOYMENT_ALIASES"
fi
But with this, even when ZEIT_DEPLOYMENT_ALIASES=['something']
it doesn't go into the then
clause.
Approach 2
ZEIT_DEPLOYMENT_ALIASES=['test.sh']
echo "Alias(es) for current project:" $ZEIT_DEPLOYMENT_ALIASES
for DEPLOYMENT_ALIAS in $ZEIT_DEPLOYMENT_ALIASES; do
[ -z "$DEPLOYMENT_ALIAS" ] || continue
echo "npx now alias "$ZEIT_DEPLOYMENT_URL $DEPLOYMENT_ALIAS
npx now alias $ZEIT_DEPLOYMENT_URL $DEPLOYMENT_ALIAS --token $ZEIT_TOKEN || echo "Aliasing failed for '$DEPLOYMENT_ALIAS', but the build will continue regardless."
done
Similarly, it seems like [ -z "$DEPLOYMENT_ALIAS" ]
always evaluate to true
.
Here is a playground if you'd like:
for DEPLOYMENT_ALIAS in "${ZEIT_DEPLOYMENT_ALIASES[@]}"
– schrodingerscatcuriosity Oct 21 '20 at 15:55ZEIT_DEPLOYMENT_ALIASES=$(cat now.$CUSTOMER_REF_TO_DEPLOY.staging.json | jq --raw-output '.alias')
is what really happens, and since it returns JSON such as['test.domain']
I assumed it would be similar in bash. (doesn't seem like) – Vadorequest Oct 21 '20 at 16:01then
clause, it has been removed by @schrodigerscatcuriosity edit, I edited again. – Vadorequest Oct 21 '20 at 16:02test.sh
? Are you expectingZEIT_DEPLOYMENT_ALIASES=['test.sh']
to run the scripttest.sh
and save the script's output in the variableZEIT_DEPLOYMENT_ALIASES
? – terdon Oct 21 '20 at 16:05test.sh
is meant to be a domain, not an executable, could have named ittest.xyz
for all that matters – Vadorequest Oct 21 '20 at 16:06null
is a bit unclear, even though the POSIX text uses it to mean an empty string. – ilkkachu Oct 21 '20 at 16:22ZEIT_DEPLOYMENT_ALIASES=$(cat now.$CUSTOMER_REF_TO_DEPLOY.staging.json | jq --raw-output '.alias')
, which is not an array, but a simple scalar string variable. And actually tells us that bynull
, you meant the actual stringnull
. (I'm not sure ifjq
can return an empty string there.) But that also tells us that your original data source is a JSON file, and you can usejq
... – ilkkachu Oct 21 '20 at 16:24['test.sh']
from, since AFAIK single quotes are not a valid way to quote strings in JSON, andjq
produces strings in double quotes. – ilkkachu Oct 21 '20 at 16:27['test.sh']
I thought it was a valid representation, didn't think single/double quotes had different meanings. – Vadorequest Oct 21 '20 at 16:28{"alias": ["foo", "bar"], "whatever": "xyzzy"}
, and you want to process thefoo
andbar
from list in thealias
field? – ilkkachu Oct 21 '20 at 16:31jq
. – Vadorequest Oct 21 '20 at 16:33jq
knows about the shell's syntax, look at the "Format strings and escaping" part of its manpage. Assuming that you have a json file of the form{"x":["a\nb","c d","e\n f"]}
, I think thateval "set -- $(jq -r '.x//empty|@sh' <file)"
(followed by e.g.for f; do printf '{%s}' "$f"; done
) should do what you want. (You may also omit the//empty
part or use the-e
option). – Oct 21 '20 at 18:42