【问题标题】:Making a copy of command line arguments inside a function在函数内复制命令行参数
【发布时间】:2017-05-28 20:36:10
【问题描述】:

目前正在开发以下版本的 Bash:

GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)

我当前的脚本:

#!/usr/bin/env bash

function main() {
  local commands=$@
  for command in ${commands[@]} ; do
    echo "command arg: $command"
  done
}

if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
  set -e
  main $@
fi

简单来说,如果是被调用的脚本,这个脚本只会执行 main,类似于 Python 的 if __name__ == '__main__' 约定。

main 函数中,我只是循环遍历所有命令变量,但引号转义并未按预期发生:

$ tests/simple /bin/bash -c 'echo true'
command arg: /bin/bash
command arg: -c
command arg: echo
command arg: true

这里的最后一个参数应该被 Bash 解析为单个参数,但它被拆分为单个单词。

我做错了什么?我希望 echo true 显示为单个参数。

【问题讨论】:

    标签: bash


    【解决方案1】:

    你得到了正确的输出,除了 'echo true' 部分正在分词。您需要在代码中使用双引号:

    main "$@"
    

    并在函数中:

    function main() {
      local commands=("$@") # need () and double quotes here
      for command in "${commands[@]}" ; do
        echo "command arg: $command"
      done
    }
    

    该函数拥有自己的$@ 副本,因此您实际上不需要制作它的本地副本。

    通过这些更改,我们得到以下输出:

    command arg: /bin/bash
    command arg: -c
    command arg: echo true
    

    一般来说,将 shell 命令存储在变量中是不好的。见BashFAQ/050

    另见:

    【讨论】:

      【解决方案2】:

      你可能想要做更多这样的事情:

      function main() {
          while [ $# -gt 0 ]
          do
              echo "$1"
              shift
          done
      }
      
      main /bin/bash -c "echo true"
      

      真正的关键是$#,它计算命令行参数的数量,(不包括调用名称$0)。环境变量$# 自动设置为命令行参数的数量。如果使用以下命令行调用函数/脚本:

      $ main /bin/bash -c "echo true"
      

      $# 的参数值为“3”:“/bin/bash”、“-c”和“echo true”。最后一个算作一个参数,因为它们用引号括起来。

      1. shift 命令将所有命令行参数向左“移动”一位。
      2. 最左边的参数丢失 (main)。

      【讨论】:

        【解决方案3】:

        引用 @ 传递给 main 是你的问题,但我想我会提到你也不需要在 main 中分配值来使用它。 您可以执行以下操作:

        main()
        {
          for command
          do
            ...
          done
        }
        
        main "$@"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-19
          • 2012-02-25
          • 2013-09-11
          • 1970-01-01
          • 2017-05-24
          • 2016-06-29
          • 2013-12-12
          • 2019-12-12
          相关资源
          最近更新 更多