在 zsh Alias 中转义反斜杠和双引号

时间:2021-01-24 12:39:11

标签: linux shell zsh

我正在尝试创建一个应转换为以下命令的别名:

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

做起来很简单

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"

在 bash 上,但在 zsh 上,命令变成

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

我无法让 "\ 逃脱。

1 个答案:

答案 0 :(得分:0)

看起来您将第一个和最后一个双引号视为整个表达式的“环绕”引号,但这不是它在 zshbash 中的工作方式。相反,这是一个由一组带引号和不带引号的字符串组成的表达式,这些字符串因为相邻而连接在一起。

一个简短的例子。这:

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

将打印:

$aY$c

只有 $a$c 是单引号,因此没有展开。

由于您示例中的某些字符(例如 [{)实际上没有被引用,因此 shell 会尝试扩展它们。它在 zsh 中失败,因为如果 glob 没有匹配项,则默认行为是退出。

有几种方法可以修复它。


选项 1 - 让 zsh 表现得像 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

不推荐这样做。有很多方法会让它失控,因为我们指望 shell 以一种精确的方式忽略特殊字符。


选项 2 - 转义内部双引号,使表达式变成一个长字符串:

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"

这也应该适用于 bash,并且在那里会是一个很好的主意。


选项 3 - 正如@chepner 建议的那样,使用更具可读性的函数:

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'
}

这也适用于 bash