简体   繁体   中英

Escaping Backslashes and Double Quotes in zsh Alias

I am trying to create an alias that should turn into the following command:

aws ssm start-automation-execution --document-name "AWS-StartEC2Instance" --document-version "\$DEFAULT" --parameters '{"AutomationAssumeRole":[""]}' --target-parameter-name InstanceId --targets '[{"Key":"ResourceGroup","Values":["DemoInstances"]}]' --max-errors "1" --max-concurrency "1" --region ap-southeast-1

It's straightforward to just do

alias startdemoinstances="aws ssm start-automation-execution --document-name "AWS-StartEC2Instance" --document-version "\$DEFAULT" --target-parameter-name InstanceId --targets "[{"Key":"ResourceGroup","Values":["DemoInstances"]}]" --max-errors "1" --max-concurrency "1" --region ap-southeast-1"

on bash, but on zsh, the command turns into

aws ssm start-automation-execution --document-name AWS-StartEC2Instance --document-version $DEFAULT --target-parameter-name InstanceId --targets '\''[{Key:ResourceGroup,Values:[DemoInstances]}]'\'' --max-errors 1 --max-concurrency 1 --region ap-southeast-1

I can't get the " or the \ to escape.

It looks like you're treating the first and last double-quotes as 'surrounding' quotes for the entire expression, but that's not how it works in either zsh or bash . Instead, that's an expression consisting of a set of quoted and unquoted strings that are concatenated because they are adjacent.

A short example. This:

a=X b=Y c=Z
echo '$a'$b'$c'

will print this:

$aY$c

only the $a and $c are in single quotes, and are therefore not expanded.

Since some of the characters in your example (eg [ , { ) are not actually quoted, the shell attempts to expand them. It fails in zsh since the default behavior is to exit if a glob has no matches.

There are several ways to fix it.


Option 1 - make zsh behave like bash:

unsetopt nomatch
alias startdemoinstances="aws ssm start-automation-execution --document-name "AWS-StartEC2Instance" --document-version "\$DEFAULT" --target-parameter-name InstanceId --targets "[{"Key":"ResourceGroup","Values":["DemoInstances"]}]" --max-errors "1" --max-concurrency "1" --region ap-southeast-1"
setopt nomatch

This is not recommended. There are a lot of ways for it to go haywire, since we're counting on the shell ignoring special characters in an exact way.


Option 2 - escape internal double-quotes, so that the expression becomes one long string:

alias startdemoinstances="aws ssm start-automation-execution --document-name \"AWS-StartEC2Instance\" --document-version \"\$DEFAULT\" --target-parameter-name InstanceId --targets \"[{\"Key\":\"ResourceGroup\",\"Values\":[\"DemoInstances\"]}]\" --max-errors \"1\" --max-concurrency \"1\" --region ap-southeast-1"

This should also work in bash , and would be a very good idea there.


Option 3 - as @chepner suggested, use a much more readable function:

function startdemoinstances {
  aws ssm start-automation-execution \
      --document-name 'AWS-StartEC2Instance' \
      --document-version "$DEFAULT" \
      --target-parameter-name 'InstanceId' \
      --targets '[{"Key":"ResourceGroup","Values":["DemoInstances"]}]' \
      --max-errors '1' \
      --max-concurrency '1' \
      --region 'ap-southeast-1'
}

This should also work in bash .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM