【问题标题】:bash: expanding function argumentsbash:扩展函数参数
【发布时间】:2014-10-28 14:47:18
【问题描述】:

我对正在编写的 shell 脚本的 bash 函数有疑问。函数如下:

do_command() {
  if [[ $DRY_RUN ]]; then
    echo $@
  else
    $@
  fi
}

功能很简单,如果设置了 DRY_RUN 标志,我们只打印方法,否则执行。这适用于大多数命令,除了我尝试过不同版本的 git tag 命令:

do_command git tag -a $NEW_VERSION -m '$INPUT_COMMENT'

这实际上执行了标记命令,但是给出了注释$INPUT_COMMENT

我已经尝试了 2 个其他版本,可以提供正确的回显输出,但不允许我执行 git tag 命令。

do_command git tag -a $NEW_VERSION -m "$INPUT_COMMENT"

do_command git tag -a $NEW_VERSION -m "\"$INPUT_COMMENT\""

有没有办法让 echo 和 git 命令在这个调用中都起作用?还是需要在do_command版本中解析?

【问题讨论】:

  • 顺便说一句,shellcheck.net 会在不需要人工审查的情况下抓住这个。
  • (顺便说一句——全大写的名称是 shell 内置函数和环境变量的常规名称,但是将它们用于常规的、非导出的变量是不好的形式,因为这意味着您可能会无意中覆盖其他类别)。
  • 请记住,do_command 之类的命令仅适用于简单命令。没有管道,没有 &&/|| 列表,没有 I/O 重定向,没有复杂的命令:除了命令名称及其参数之外,没有什么需要语法。
  • @CharlesDuffy 感谢您的反馈,总是很好地使用在线工具来帮助您,将所有变量更新为小写。

标签: git bash function shell


【解决方案1】:

使用带有引号的"$@" 来正确处理带有空格的参数。如果您只写$@,那么当$INPUT_COMMENT 包含空格时,git 命令将不起作用。

do_command() {
  if [[ $DRY_RUN ]]; then
    echo "$@"
  else
    "$@"
  fi
}

用法:

do_command git tag -a $NEW_VERSION -m "$INPUT_COMMENT"

【讨论】:

  • 我建议 printf '%q ' "$@"; echo 代替 DRY_RUN 案例;这样输出在视觉上区分 "foo bar" bazfoo bar baz
  • 我提倡在每次使用变量时使用双引号(除非您明确希望在值中使用空格产生效果),所以也要使用"$DRY_RUN""$NEW_VERSION"。如果DRY_RUN"true""false",你可以简单地写if "$DRY_RUN"; then。使其更具可读性。
  • @Alfe, ...好吧,[[ ]] 是个例外; $DRY_RUN 不需要在此处引用,因为上下文隐式地防止了字符串拆分和全局扩展。不过,作为一般规则,您是完全正确的。
  • @Alfe,(另外,我倾向于考虑将 truefalse 用作非常差的形式,因为将它们评估为命令意味着您正在运行任意命令,如果您编写的脚本的参数跨越权限边界,这是一个危险的习惯;像这里所做的那样测试空与非空,或零与非零等要好得多。
  • @CharlesDuffy 您在安全方面是对的。但是,如果您只是使用自己的代码并且只使用自己的变量、标志等,我认为可读性胜过模糊的安全问题。但问题是人们永远不知道脚本或其一部分是否会在以后用于不同的上下文中。因此,如果您对此感到担忧,您可能会觉得使用 0/1 或空/非空值以及像 if [ "$flag" = 1 ]; then 这样的测试更安全。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-19
相关资源
最近更新 更多