将 args 从 bash 脚本传递到脚本中的函数

将 args 从 bash 脚本传递到脚本中的函数

我的脚本:

#! /bin/bash --

set -x

## docker-compose wrapper
compose_fn() {
  local ENV="${1}"
  local VERB="${2}"
  local SERVICE="${3}"
  local CMD="docker-compose -f ${ENV}.yml"
  case "${VERB}" in
    (exec)
      shift "$#" # remove args passed to this fn
      # Execute a command in a running container.
      if [ -n "${SERVICE}" ]; then
        ${CMD} "${VERB}" "${SERVICE}" "$@"
      else
        echo "## Err: You must specify service name..."
        exit 1
      fi
    ;;
  esac
}

compose_fn "${1}" "${2}" "${3}"

以下错误让我很难受:

$ ./tst.sh dev exec django sh
+ compose_fn dev exec django
+ local ENV=dev
+ local VERB=exec
+ local SERVICE=django
+ local 'CMD=docker-compose -f dev.yml'
+ case "${VERB}" in
+ shift 3
+ '[' -n django ']'
+ docker-compose -f dev.yml exec django
Execute a command in a running container

Usage: exec [options] [-e KEY=VAL...] SERVICE COMMAND [ARGS...]

Options:
....

我的错误在哪里?怎样才能做得更好呢?

据我所知,我已将 4 个参数传递[dev, exec, django, sh]给脚本,然后在脚本中删除了 3 个 ( shift 3),因此sh应该保留在$@var 中。

答案1

shift "$#"$@彻底空虚。$@函数中的 与主脚本中的 是分开的$@。既然您确切地知道$@需要在函数中使用和关闭脚本的多少元素,为什么不直接传递全部函数的参数然后移走前三个?

#! /bin/bash --

set -x

## docker-compose wrapper
compose_fn() {
  local env="$1"
  local verb="$2"
  local service="$3"

  local cmd=( docker-compose -f "$env.yml" )

  shift 3 # we've now used up three arguments

  case $verb in
      exec)
          # Execute a command in a running container.
          if [ -n "$service" ]; then
              "${cmd[@]}" "$verb" "$service" "$@"
          else
              echo '## Err: You must specify service name...' >&2
              exit 1
          fi
          ;;
      *)
          printf 'Unknown verb: %s\n' "$verb" >&2
          exit 1
    esac
}

compose_fn "$@"

我还使用了小写变量名,这样就不会意外使用系统或特殊 shell 变量(ENV例如,某些 shell 在某些情况下使用的变量),并且我删除了所有不需要的引号和大括号。

我还将命令放入一个数组中,以便我们可以正确引用 YAML 文件名。

您还可以将三个变量的设置移到函数之外,具体取决于脚本的其余部分的外观以及这是否有意义。这三个变量将在脚本中成为全局变量。

#! /bin/bash --

set -x

## docker-compose wrapper
compose_fn() {
  local cmd=( docker-compose -f "$env.yml" )

  case $verb in
      exec)
          # Execute a command in a running container.
          if [ -n "$service" ]; then
              "${cmd[@]}" "$verb" "$service" "$@"
          else
              echo '## Err: You must specify service name...' >&2
              exit 1
          fi
          ;;
      *)
          printf 'Unknown verb: %s\n' "$verb" >&2
          exit 1
    esac
}

env="$1"
verb="$2"
service="$3"

shift 3

compose_fn "$@"

您也可以绕过[ -n "$service" ]测试

service=${3:?'## Err: You must specify service name...'}

参数扩展${parameter:?word}将退出 shell,并显示wordifparameter未设置或为空定义的消息。 shellbash会将其格式化为

script.sh: line 9: 3: ## Err: You must specify service name...

有关的:

相关内容