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.
Advertisement
Answer
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 (e.g. [
, {
) 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
.