我知道我可以很容易地在bash中获得这样的定位参数:

$0或$1

我希望能够使用这样的标志选项来指定每个参数的使用:

mysql -u user -h host

获得-u参数值和-h参数值的最佳方法是通过标志而不是通过位置?


当前回答

这是我常用的成语:

while test $# -gt 0; do
  case "$1" in
    -h|--help)
      echo "$package - attempt to capture frames"
      echo " "
      echo "$package [options] application [arguments]"
      echo " "
      echo "options:"
      echo "-h, --help                show brief help"
      echo "-a, --action=ACTION       specify an action to use"
      echo "-o, --output-dir=DIR      specify a directory to store output in"
      exit 0
      ;;
    -a)
      shift
      if test $# -gt 0; then
        export PROCESS=$1
      else
        echo "no process specified"
        exit 1
      fi
      shift
      ;;
    --action*)
      export PROCESS=`echo $1 | sed -e 's/^[^=]*=//g'`
      shift
      ;;
    -o)
      shift
      if test $# -gt 0; then
        export OUTPUT=$1
      else
        echo "no output dir specified"
        exit 1
      fi
      shift
      ;;
    --output-dir*)
      export OUTPUT=`echo $1 | sed -e 's/^[^=]*=//g'`
      shift
      ;;
    *)
      break
      ;;
  esac
done

要点如下:

$#是参数的个数 While循环查看提供的所有参数,在case语句中匹配它们的值 Shift移走了第一个。您可以在case语句中多次移位以获取多个值。

其他回答

Getopt是你的朋友。举个简单的例子:

function f () {
TEMP=`getopt --long -o "u:h:" "$@"`
eval set -- "$TEMP"
while true ; do
    case "$1" in
        -u )
            user=$2
            shift 2
        ;;
        -h )
            host=$2
            shift 2
        ;;
        *)
            break
        ;;
    esac 
done;

echo "user = $user, host = $host"
}

f -u myself -h some_host

在您的/usr/bin目录中应该有各种示例。

#!/bin/bash

if getopts "n:" arg; then
  echo "Welcome $OPTARG"
fi

保存为sample.sh 试着跑步

sh sample.sh -n John

在你的终端。

这是我常用的成语:

while test $# -gt 0; do
  case "$1" in
    -h|--help)
      echo "$package - attempt to capture frames"
      echo " "
      echo "$package [options] application [arguments]"
      echo " "
      echo "options:"
      echo "-h, --help                show brief help"
      echo "-a, --action=ACTION       specify an action to use"
      echo "-o, --output-dir=DIR      specify a directory to store output in"
      exit 0
      ;;
    -a)
      shift
      if test $# -gt 0; then
        export PROCESS=$1
      else
        echo "no process specified"
        exit 1
      fi
      shift
      ;;
    --action*)
      export PROCESS=`echo $1 | sed -e 's/^[^=]*=//g'`
      shift
      ;;
    -o)
      shift
      if test $# -gt 0; then
        export OUTPUT=$1
      else
        echo "no output dir specified"
        exit 1
      fi
      shift
      ;;
    --output-dir*)
      export OUTPUT=`echo $1 | sed -e 's/^[^=]*=//g'`
      shift
      ;;
    *)
      break
      ;;
  esac
done

要点如下:

$#是参数的个数 While循环查看提供的所有参数,在case语句中匹配它们的值 Shift移走了第一个。您可以在case语句中多次移位以获取多个值。

这个例子使用了Bash内置的getopts命令,来自谷歌Shell样式指南:

a_flag=''
b_flag=''
files=''
verbose='false'

print_usage() {
  printf "Usage: ..."
}

while getopts 'abf:v' flag; do
  case "${flag}" in
    a) a_flag='true' ;;
    b) b_flag='true' ;;
    f) files="${OPTARG}" ;;
    v) verbose='true' ;;
    *) print_usage
       exit 1 ;;
  esac
done

注意:如果一个字符后面跟着一个冒号(例如f:),该选项应该有一个参数。

使用示例:./script -v -a -b -f filename . txt

使用getopts比接受的答案有几个优点:

while条件可读性更强,并显示了接受的选项是什么 清洁代码;不计算参数个数和移位 您可以连接选项(例如-a -b -c→-abc)

然而,一个很大的缺点是它不支持长选项,只支持单字符选项。

我在使用带有多个标志的getopts时遇到了麻烦,所以我编写了这段代码。它使用一个模态变量来检测标志,并使用这些标志为变量分配参数。

注意,如果一个标志不应该有参数,除了设置CURRENTFLAG之外,还可以执行其他操作。

    for MYFIELD in "$@"; do

        CHECKFIRST=`echo $MYFIELD | cut -c1`

        if [ "$CHECKFIRST" == "-" ]; then
            mode="flag"
        else
            mode="arg"
        fi

        if [ "$mode" == "flag" ]; then
            case $MYFIELD in
                -a)
                    CURRENTFLAG="VARIABLE_A"
                    ;;
                -b)
                    CURRENTFLAG="VARIABLE_B"
                    ;;
                -c)
                    CURRENTFLAG="VARIABLE_C"
                    ;;
            esac
        elif [ "$mode" == "arg" ]; then
            case $CURRENTFLAG in
                VARIABLE_A)
                    VARIABLE_A="$MYFIELD"
                    ;;
                VARIABLE_B)
                    VARIABLE_B="$MYFIELD"
                    ;;
                VARIABLE_C)
                    VARIABLE_C="$MYFIELD"
                    ;;
            esac
        fi
    done