我有一个函数,它取决于功能发生变化的参数。
我知道我能做到:
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 的等效项来处理长选项和操作数。