带选项的 Shell 脚本

带选项的 Shell 脚本

我正在编写一个 shell 脚本,最多接受 2 个选项。但是,我有一个问题。你能帮我吗? (假设该脚本的名称是command。)

#!/bin/bash
PROGNAME=$(basename $0)
for OPT in "$@"
do
    echo "OPT: $OPT"
    case "$OPT" in
            '-p' | '--password' )
                    if [[ -z "$2" ]] || [[ "$2" =~ ^-+ ]]
                    then
                            echo "$PROGNAME: option requires an argument -- '$(echo $1 | sed 's/^-*//')'"
                            exit 2
                    fi
                    PASSWORD="$2"
                    shift 2
                    ;;
            '-u' | '--user' )
                    if [[ -z "$2" ]] || [[ "$2" =~ ^-+ ]]
                    then
                            echo "$PROGNAME: option requires an argument -- '$(echo $1 | sed 's/^-*//')'"
                            exit 2
                    fi
                    USER="$2"
                    shift 2
                    ;;
            * )
                    echo "$1"
                    echo "$PROGNAME: illigal option or argument -- '$(echo $1 | sed 's/^-*//')'"
                    exit 1
                    ;;
    esac
done
echo "GOOD"

测试1

$./command 
GOOD

测试2

$./command -u user
OPT: -u
OPT: user

command: illigal option or argument -- ''

(第四行是空的。)

测试3

$./command -u user -p passwd
OPT: -u
OPT: user
-p
command: illigal option or argument -- 'p'

所有 -u、--user、-p 和 --password 都会发生同样的情况。我有 3 个问题。

1)为什么test2和test3中会出现“OPT:user”?

2)如果我给它一个选项,为什么这段代码会导致错误?

3)如何修复此代码?我真的很感谢你的帮助!

答案1

你的扩展"$@"发生在循环的开始for;内部shift不会有任何影响。

例如

for a in "$@"
do
  echo OPTION: $a
  shift 2
done

有了这个:

$ bash x a b c d e f
OPTION: a
OPTION: b
OPTION: c
OPTION: d
OPTION: e
OPTION: f

我们可以看到shift没有做任何事情

相反,您希望每次都重新评估它:

$ cat x             
while [ $# -gt 0 ]
do
  a="$1"
  echo OPTION: $a
  shift 2
done

$ bash x a b c d e f
OPTION: a
OPTION: c
OPTION: e

(您需要做比这更好的测试;如果您传递奇数个参数,则此示例代码永远不会终止,因为失败shift 2

答案2

我曾经使用 while/shift 循环

#! /bin/bash
PROGNAME=$(basename $0)
while [ -n "$1" ]
do
  echo "OPT: $1"
  case "$1" in
    --user=* )
      if [[ "$1" =~ --user=(.+) ]]
      then
        USER=${BASH_REMATCH[1]}
      else
        echo "$PROGNAME: option requires an argument -- $1"
        exit 2
      fi
      ;;
    -u )
      if [ -z "$2" ]
      then
        echo "$PROGNAME: option requires an argument -- $1"
        exit 2
      fi
      USER="$2"
      shift
      ;;
    * )
      echo "$PROGNAME: illigal option or argument -- $1"
      exit 1
      ;;
  esac
  shift
done
[ -n "$USER" ] && echo "USER: $USER"
echo "GOOD"

$USER它是一个坏变量,因为它已经设置了。

相关内容