使用 getopts 分隔参数

Separating arguments with getopts

所以,我正在尝试编写一个脚本

1.) 使用用户指定的名称创建一个新目录

2.) 从远程位置下载文件到新目录

3.) 将端口附加到新目录中的文件

我现在拥有的是

OPTIND=1 
while getopts "hpnm:" opt; do
case "$opt" in
    h)
        show_help
        exit 0
        shift
        ;;
    p)  port="*@"
        shift
        /home/servers/zombies/"$server_name"/server.properties >> port: "$@" 
        ;;
    n)  server_name="$*"
        shift
        mkdir /home/ecb/servers/zombies/"$*"
        ;;
    m)  map_name="$*"
        shift
        rsync -azvP username@host:/home/downloads/zombies/"$*" /home/servers/zombies/"$server_name"/
        ;;
esac
done

当我 运行 脚本时,它会将“-n Test -m test -p 1234”解释为 "Test test 1234"。我将如何分隔参数?

  1. 不要shift。这会使 getopts 感到困惑,因为您正在修改正在工作的参数列表。

  2. 如果一个选项接受一个参数,在参数向量中的字符后面放一个冒号。在你的例子中,-p-n-m 都接受参数,而不仅仅是 -m。所以你的调用应该是:

    while getopts "hp:n:m:" opt; do
    
  3. 要引用选项参数,请使用 $OPTARG。 getops 会将参数放入该变量(前提是您告诉 getopts 该选项需要一个参数)。

  4. 当 getopts 完成时,OPTIND 将是第一个位置参数的索引。此时,如果你愿意,你可以移走所有消耗的参数:

    shift $((OPTIND-1))
    

    或者您可以使用 bash 的子序列符号扫描它们:

    for arg in "${@:OPTIND}"; do
    
  5. 立即根据选项采取行动通常不是一个好主意。相反,您通常会将每个参数保存到一个变量中,并在选项解析完成时处理这些变量。有几个原因:

    • 您可能会在识别第一个选项后检测到错误。在这种情况下,您通常希望在不改变世界状态的情况下生成一条错误消息。

    • 通常,选项没有指定的顺序(这就是为什么它们用选项字母标识,而不是位置)。通常情况下,按特定顺序执行操作会更好。

    • 根据定义,选项是可选的。但是在到达列表末尾之前,您不知道某个选项是未指定的。如果选项有默认值,或者如果选项的非规范影响脚本的行为,您可能想在开始操作之前了解它。

  6. 通常不需要初始化 OPTIND,因为 bash 在创建新的执行环境时会自动初始化。