Home > Mobile >  how do I use powershell variable in AWS CLI command
how do I use powershell variable in AWS CLI command

Time:06-14

I am trying to run AWS CLI in Powershell 7 with a JSON string as parameter. AWS docs make it seem straightforward:

aws route53 ... --change-batch '{"Changes":[{"Action":"UPSERT"}]}'

however, I get an error:

Error parsing parameter '--change-batch': Invalid JSON: Expecting property name enclosed in double quotes: line 1 column 2 (char 1) JSON received: {Changes:[{Action:UPSERT ...

So, it looks like double quotes are stripped at some point.

If I escape the quotes, command works:

aws route53 ... --change-batch '{\"Changes\":[{\"Action\":\"UPSERT\"}]}'

Now, I am trying to use a variable:

aws route53 ... --change-batch '{\"Changes\":[{\"Action\":\"UPSERT\", \"Value\":\"$MY_IP\"}]}'

but the variable is not resolved; that is, $MY_IP is passed to the server. I tried putting the whole string in double-quotes - but it looks like with double quotes internal quotes are removed even if I escape them. Also with backticks - it works as command continuation. I am looking at Microsoft docs - but the results I am getting are clearly different.

I don't think the problem has anything to do with AWS, but AWS CLI gave me a super twisted test case.

CodePudding user response:

  • Fundamentally, PowerShell only performs string interpolation in double-quoted strings ("..."), also known as expandable strings: see this answer.

  • The surprising and unfortunate need to explicitly \-escape embedded " chars. in arguments for external programs applies irrespective of which quoting style you use, up to at least PowerShell 7.2.x: see this answer.

Thus, since you need a "..." string for string interpolation (so that variable reference $MY_IP is expanded to its value), you need two layers of escaping of embedded ":

  • `" (or "") in order to satisfy PowerShell's syntax requirements...

  • ... and this escape sequence must additionally be escaped with \ in order for the external program to see the embedded " as such.

Therefore:

# Inside "...", pass-through " must be escaped as \`" (sic)
aws route53 ... --change-batch "{\`"Changes\`":[{\`"Action\`":\"`UPSERT\`", \`"Value\`":\`"$MY_IP\`"}]}"

You can ease the pain with the help of an (expandable) here-string, which obviates the need to escape the embedded " for PowerShell's sake:

# A here-string obviates the need to escape " for PowerShell's sake.
aws route53 ... --change-batch @"
{\"Changes\":[{\"Action\":\"UPSERT\", \"Value\":\"$MY_IP\"}]}
"@

Another option is to perform the \-escaping after the fact, programmatically:

aws route53 ... --change-batch (@"
{"Changes":[{"Action":"UPSERT", "Value":"$MY_IP"}]}
"@ -replace '"', '\"')
  • Related