将布尔标志传递给函数?

将布尔标志传递给函数?

我有一个函数,它取决于功能发生变化的参数。
我知道我能做到:

function foo {  
  PARAM1=$1  
  PARAM2="$2"  
  VAR=$3  
  if[[ -z "$VAR" ]]; then  
   # code here  
  else  
   # other code here  
  fi  
}  

我想知道 bash 是否有更合适的方法。这会起作用,但我不希望有类似的东西

foo "x" "y" "blah"  
foo "x" "y" "true"  
foo "y" "y" "1"

一切都是等价的。

有没有更适合 Bash 的方法?

答案1

您可以为您的函数提供命令行选项。使用不带参数的命令行选项是向 shell 脚本、shell 函数和实用程序提供二进制/布尔值(“开/关”、“真/假”、“启用/禁用”)的常见方法。

foo () {
    local flag=false
    OPTIND=1

    while getopts 't' opt; do
        case $opt in
            t) flag=true ;;
            *) echo 'Error in command line parsing' >&2
               exit 1
        esac
    done
    shift "$(( OPTIND - 1 ))"

    local param1="$1"
    local param2="$2"

    if "$flag"; then
        # do things for "foo -t blah blah"
    else
        # do things for "foo blah blah"
    fi
}

该选项-t对于用户来说就像一个布尔标志。使用它会将flag函数内部设置为true(将其默认值更改为false)。该-t选项将用作函数的第一个参数。

调用该函数可以使用

foo "some value" "some other value"

或者

foo -t "some value" "some other value"

其中后一个调用会将flag函数中的变量设置为true.

答案2

一般来说

一般来说,在任何语言中将布尔值传递给函数都是不可读的。例如calculate_interest 5y 4% true。读者不禁想知道什么是真实的。

因此使用枚举:{ per_month, per_year }。现在你可以做calculate_interest 5y 4% per_year。这更具可读性。

在bash中

Bash 不是静态类型的(或强类型的,或者根本没有很多类型系统),因此您可以传递许多不同的值。一个人会走这条路,其他人则不会。我们不希望有许多不同的价值观导致同一条道路。

因此,添加代码来检查输入是否是两个可接受的值之一。在函数开始时执行此操作,您不想在完成某件事后 1/2 退出。

如果必须调用采用布尔值的函数该怎么办

所以有人没有听从我的建议,你必须调用一个带有布尔值的函数。你可以做什么来让你的代码可读?

  • 如果语言(例如Python)允许命名参数eg calculate_interest 5y 4% per_year=True,则使用它们。它会有所帮助,但不会告诉您 的含义calculate_interest 5y 4% per_year=False
  • 如果语言没有命名参数,那么唯一的选择就是接受不可读的代码(不是选项),或者将函数包装在可读写的函数中。

答案3

我建议遵循这样的格式:

foo() {
  # Limit scope of variables
  local 'opt1' 'opt2' 'opt3' 'operands'

  # Default values
  opt1='default1'
  opt2='default2'
  opt3='false'
  operands=()

  # Arguments handling
  while (( ${#} > 0 )); do
    case "${1}" in
      ( '--opt1='* ) opt1="${1#*=}" ;;           # Handles --opt1
      ( '--opt2='* ) opt2="${1#*=}" ;;           # Handles --opt2
      ( '--opt3='* ) opt3="${1#*=}" ;;           # Handles --opt3
      ( '--' ) operands+=( "${@:2}" ); break ;;  # End of options
      ( '-'?* ) ;;                               # Discard non-valid options
      ( * ) operands+=( "${1}" )                 # Handles operands
    esac
    shift
  done

  ...
}

这样该函数将更加健壮和可读:

$ foo
Options:
  opt1: [default1]
  opt2: [default2]
  opt3: [false]
$ foo --opt1='value1' --opt2='value2' --opt3='true' 'foo' 'bar' 'baz'
Options:
  opt1: [value1]
  opt2: [value2]
  opt3: [true]
Operands:
  1: [foo]
  2: [bar]
  3: [baz]

优点:

  • 易于阅读和理解。
  • 语法与任何典型的命令行实用程序类似。
  • 可以轻松添加更多选项,而不会破坏兼容性。

缺点:

  • 对于小而简单的脚本来说可能有点过分了。
  • 很难编写一个可移植且兼容 POSIX 的等效项来处理长选项和操作数。

相关内容