已复制
全屏展示
复制代码

bash解析命令行参数


· 4 min read

一. 命令行参数

在不借助任何函数来获取命令行参数的情况下,$0 表示脚本执行的脚本名称,$1 表示第一个参数, $2 表示第二个参数。。。

  • /tmp/test.sh
#!/bin/bash
echo $0 $1 $2
  • 执行 /tmp/test.sh 输出结果
$ bash /tmp/test.sh a b
/tmp/test.sh a b
  • 注意:如果参数超过了9个,需要使用大括号,比如 $9 ${10} ${11} ,因为$ 后面有多个数字,并且没有大括号时,它只会把第一个数字当做位置参数.
$ cat /tmp/test.sh 
#!/bin/bash
echo $0 $1 $2 $9 $10 ${10}


$ bash /tmp/test.sh 1 2 3 4 5 6 7 8 9 10
/tmp/test.sh 1 2 9 10 10

如果需要更复杂的命令行参数解析,则需要使用 额外的 getopts getopt 等函数。

二. getopts 函数

  • getopts后面的字符串表示定义的选项列表,每个字母代表一个选项。
  • 后面带:表示该选项有值,后面不带:表示该选项没有值。
  • 如果选项列表中第一个是 : 表示不打印错误信息。
  • 它的缺点是只能使用短选项。为了使用长选项请使用 getopt 函数
# test_getopts.sh

#!/bin/bash
usage(){
    command=$(basename $0)
    echo "NAME"
    echo "    $command - send message to someone"
    echo "SYNOPSIS"
    echo "    $command [OPTIONS]..."
    echo "DESCRIPTION"
    echo "    Send message to someone by all kinds of methods. default is to yourself."
    echo "OPTIONS"
    echo "    -p  by phone."
    echo "    -w  by wechat."
    echo "    -u <USERNAME>"
    echo "        send to someone."
    echo "    -t <TIMES>"
    echo "        if fails then retry times."
    echo "EXAMPLES"
    echo "    $command -t 5 -p -u root"
    echo "        send message to root by telephone, if fails then retry 5 times."
    echo "    $command -t 5 -p -u root -u mysql"
    echo "        send message to root and mysql by telephone, if fails then retry 5 times."
    echo
}

[ $# -eq 0 ] && usage && exit 1
while getopts ":hpwu:t:" arg
do
    case "$arg" in
        p) method="phone"
           ;;
        w) method="wechat"
           ;;
        u) if [ -z "$user" ];then user=$OPTARG; else user="${user}:$OPTARG"; fi
           ;;
        t) times=$OPTARG
           ;;
        h | *) usage; exit 1
           ;;
    esac
done

echo "method: $method"
echo "user: $user"
echo "times: $times"

如上的例子执行结果如下

$ bash test_getopts.sh -p -uroot -u backup -t 5
method: phone
user: root:backup
times: 5

三. getopt  函数

● -a 可以是短选项比如 -user root
● -q 如果有错误的选项,不会报错
● -o 选项后面接可接受的短选项,如xy:z:: 表示可接受的短选项为-x -y -z
  ○ -x 选项不接参数。
  ○ -y 选项后必须接参数。
  ○ -z 选项的参数为可选参数,且可选参数必须紧贴选项。
● -l 选项后面接可接受的长选项,用逗号分开,冒号的意义同短选项。
# test_getopt.sh

#!/bin/bash
ARGS=$(getopt -a -q -o hu:t:m:: -l help,user:,times: -- "$@")
[ $? != 0 ] && echo "use -h or --help see help message" && exit 1
usage(){
    command=$(basename $0)
    echo "NAME"
    echo "    $command - send message to someone"
    echo "SYNOPSIS"
    echo "    $command [OPTIONS]..."
    echo "DESCRIPTION"
    echo "    Send message to someone by all kinds of methods. default is to yourself."
    echo "OPTIONS"
    echo "    -h, --help"
    echo "        show this message."
    echo "    -u, --user <USERNAME>"
    echo "        send to someone."
    echo "    -t, --times <TIMES>"
    echo "        retry times."
    echo "    -m [phone|wechat]"
    echo "        which method do you want. default to phone."
    echo "EXAMPLES"
    echo "    $command -t 5 -u root -mphone"
    echo "        send message to root by telephone, if fails then retry 5 times."
    echo "    $command -t 5 -u root -u mysql"
    echo "        send message to root and mysql by telephone, if fails then retry 5 times."
    echo
}

[ $? -ne 0 ] && usage
eval set -- "${ARGS}"
while true
do
    case "$1" in
        -u|--user)
            if [ -z "$user" ];then user="$2"; else user="${user}:$2"; fi
            shift 2
            ;;
        -t|--times)
            times="$2"
            shift 2
            ;;
        -m)
            case "$2" in
                "") method="phone"; shift 2 ;;
                * ) method="$2"; shift 2 ;;
            esac
            ;;
        -h|--help) usage; exit 0;;
        --) shift; break;;
    esac
done

echo "user: $user"
echo "times: $times"
echo "method: $method"

# other sub command
target=$(for arg do echo "$arg"; done)
echo $target

执行上面的示例结果如下


$ bash test_getopt.sh -uroot -u mysql -user backup -m -t8 start
user: root:mysql:backup
times: 8
method: phone
start

四. 选项标准化

在创建 shell 脚本时,尽量保持选项与 Linux 通用的选项含义相同,Linux 通用选项有

# 通用选项有
-a 显示所有对象
-c 生产一个计数
-d 指定一个目录
-e 扩展一个对象
-f 指定读入数据的文件
-h 显示命令的帮助信息
-i 忽略文本大小写
-l 产生输出得长格式文本
-n 使用非交互模式
-o 指定将所有输出重定向到输出文件
-q 以安静模式运行    
-r 递归的处理目录和文件
-s 以安静模式运行    
-v 生成详细输出  
-x 排除某个对象 
-y 对所有问题回答yes

文章推荐