Home > database >  Export multiple environment variables extracted from a single jq invocation
Export multiple environment variables extracted from a single jq invocation

Time:02-05

When I use

<some commands that output a json> | jq -r '.Credentials | .AccessKeyId, .SecretKey, .SessionToken'

I get the following output:

ABCDEF
123456
AAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBB

Three distinct lines with various keys.

I would like to export these outputs as exports:

export AWS_ACCESS_KEY_ID=<the first line of the output>
export AWS_SECRET_KEY=<the second line of the output>
export AWS_SESSION_TOKEN=<the third line of the output>

How do I do that (and still remain with oneliner)?

I tried doing the following:

<some commands that output a json> | jq -r '.Credentials | .AccessKeyId, .SecretKey, .SessionToken' | export AWS_ACCESS_KEY_ID=`awk 'NR==1'`

and it works but

<some commands that output a json> | jq -r '.Credentials | .AccessKeyId, .SecretKey, .SessionToken' | export AWS_ACCESS_KEY_ID=`awk 'NR==1'; export AWS_SECRET_KEY=`awk 'NR==2'`

hangs.

I'm using zsh.

CodePudding user response:

An option not yet discussed by other answers is using the jq @sh filter to generate code that's directly safe to eval.

eval "$(printf '%s\n' "$json" | jq -r '
  .Credentials | ("export AWS_ACCESS_KEY=\(.AccessKeyId | @sh)",
                  "export AWS_SECRET_KEY=\(.SecretKey | @sh)",
                  "export AWS_SESSION_TOKEN=\(.SessionToken | @sh)")')"

Note that the above could trivially be one line, and was broken up to generate three separate shell commands only for the sake of readability:

eval "$(printf '%s\n' "$json" | jq -r '.Credentials | "export AWS_ACCESS_KEY=\(.AccessKeyId | @sh) AWS_SECRET_KEY=\(.SecretKey | @sh) AWS_SESSION_TOKEN=\(.SessionToken | @sh)"')"

One advantage of this approach, which no other answers currently provide as-written, is that it will correctly handle keys or tokens that contain literal newlines.

CodePudding user response:

As suggested by Charles Duffy, you can use something like this:

{ read -r AWS_ACCESS_KEY_ID && read -r AWS_SECRET_KEY && read -r AWS_SESSION_TOKEN; } << EOF
$(<some commands that output a json> | jq -r '.Credentials | .AccessKeyId, .SecretKey, .SessionToken')
EOF
export AWS_ACCESS_KEY_ID AWS_SECRET_KEY AWS_SESSION_TOKEN

Also, as suggested by Charles, you can use a here string, like this:

{ read -r AWS_ACCESS_KEY_ID && read -r AWS_SECRET_KEY && read -r AWS_SESSION_TOKEN; } <<<"$(some commands that output a json | jq -r '.Credentials | .AccessKeyId, .SecretKey, .SessionToken')"
export AWS_ACCESS_KEY_ID AWS_SECRET_KEY AWS_SESSION_TOKEN

And here is a proof of concept:

$ unset a b c

$ { read -r a && read -r b && read -r c; }<< EOF
$(cat t.txt)
EOF

$ echo $a $b $c
ABCDEF 123456 AAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBB

$ unset a b c

$ { read -r a && read -r b && read -r c; }<<<"$(cat t.txt)"

$ echo $a $b $c
ABCDEF 123456 AAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBBAAAAAABBBBB

CodePudding user response:

I'd do it like this:

for i in AWS_ACCESS_KEY_ID AWS_SECRET_KEY AWS_SESSION_TOKEN; do
    read "$i" &&
    export "$i"
done \
< <(json commands |
jq -r '...')

The variables are only exported if something is successfully read. If you want them exported regardless (empty), just remove the "and" operator (&&).

  •  Tags:  
  • Related