Shell脚本:转义参数列表,包括哈希符号(#)

时间:2016-07-06 21:51:18

标签: bash shell parameters escaping

我为自己编写了一个自定义shell脚本,以便我更轻松地将代码提交给Github。

最近,我想开始使用Github通过在提交消息中包含它们的号码来自动关闭问题的能力:

# Would automatically close #1 on push
git add .
git commit -m "Closes issue #1 ..."
git push

但是,我的脚本设置方式,它使用$*抓取所有参数,但会自动删除#符号后面的任何内容,因为这是shell脚本中的注释。

commit() {
  # Print out commands for user to see
  echo "=> git add ."
  echo "=> git commit -m '$*'"
  echo "=> git push --set-upstream origin $current_branch"

  # Actually execute commands
  git add .
  git commit -m "$*"
  git push --set-upstream origin $current_branch
}

现在我可以使用包装引号commit 'Closes issue #1 ...',但这有点烦人......我专门设置了我的脚本,所以我可以轻松地写:commit Whatever message I want to put in here...

我查看了手册页并做了一些SO搜索,但我找不到任何关于转义#符号作为参数的具体问题。

这甚至可能吗?

2 个答案:

答案 0 :(得分:3)

#之后的任何内容都被shell解释为注释,因此它不会传递给函数。这在执行函数之前发生。功能无法阻止这一点。

有两种规范方法可以做到这一点:

  • 只需要引用。每个接受命令行参数的Unix工具都需要这个。
  • 让程序从stdin读取提交,而不是read -r input。然后,您只需运行commit并输入消息。

这些都是很好的解决方案,因为它们是简单,熟悉,透明,健壮,惯用的Unix,可以直接推理。使用 Unix 总是比使用更好。

然而,如果您更喜欢复杂,不熟悉,不透明,脆弱的特殊情况,您可以使用魔术别名和历史记录它:

commit() {
  echo "You wrote: $(HISTTIMEFORMAT= history 1 | cut -d ' ' -f 2-)"
}
alias commit="commit # "

以下是一个例子:

$ commit This is text with #comments and mismatched 'quotes and * and $(expansions)
You wrote: commit This is text with #comments and mismatched 'quotes and * and $(expansions)

答案 1 :(得分:1)

只是玩了一点

脚本

commit() {
  echo "$*"
}

脚本的用法和输出

➜  ~ commit "whatever you want #1 for some reason" 
whatever you want #1 for some reason
➜  ~ commit 'whatever you want #1 for some reason'
whatever you want #1 for some reason
➜  ~ commit whatever you want \#1 for some reason 
whatever you want #1 for some reason
➜  ~ commit whatever you want #1 for some reason 
whatever you want
➜  ~ 

所以,如果您不想引用消息,则需要使用\(反斜杠)来转义散列,这实际上是一个常规转义字符