我有以下 bash 函数:
lscf() {
while getopts f:d: opt ; do
case $opt in
f) file="$OPTARG" ;;
d) days="$OPTARG" ;;
esac
done
echo file is $file
echo days is $days
}
使用参数运行此命令不会输出任何值。只有在不带参数运行该函数,然后再次使用参数运行该函数后,它才会输出正确的值:
-bash-4.1$ lscf -d 10 -f file.txt
file is
days is
-bash-4.1$ lscf
file is
days is
-bash-4.1$ lscf -d 10 -f file.txt
file is file.txt
days is 10
我错过了什么吗?
答案1
虽然我无法重现您问题中函数的初始运行,但您应该OPTIND
在函数中重置为 1,以便能够在重复调用函数时处理函数的命令行。
从bash
手册:
OPTIND
每次调用 shell 或 shell 脚本时都会初始化为 1。当选项需要参数时,getopts
将该参数放入变量 中OPTARG
。 外壳不会OPTIND
自动重置;getopts
如果要使用一组新参数,则必须在同一 shell 调用中的多次调用之间手动重置它。
从POSIX 标准:
如果应用程序设置
OPTIND
为值 1,则可以使用一组新参数:当前位置参数或新的 arg 值。getopts
任何其他尝试在单个 shell 执行环境中使用在所有调用中都不相同的参数(位置参数或 arg 操作数)或将OPTIND
值修改为 1 以外的值来多次调用,都会产生未指定的结果。
手册中提到的“shell 调用”bash
与 POSIX 文本中提到的“单执行环境”相同,都是指您的 shell 脚本或交互式 shell。在脚本或交互式 shell 中,对您的多次调用将在同一环境中lscf
调用,并且需要在每次此类调用之前重置为 1。getopts
OPTIND
所以:
lscf() {
OPTIND=1
while getopts f:d: opt ; do
case $opt in
f) file="$OPTARG" ;;
d) days="$OPTARG" ;;
esac
done
echo file is $file
echo days is $days
}
如果变量file
和days
应该不是在调用 shell 的环境中设置,它们应该是局部变量。另外,引用变量扩展并用于printf
输出变量数据:
lscf() {
local file
local days
OPTIND=1
while getopts f:d: opt ; do
case $opt in
f) file="$OPTARG" ;;
d) days="$OPTARG" ;;
esac
done
printf 'file is %s\n' "$file"
printf 'days is %s\n' "$days"
}