需要对 shell 脚本进行特殊验证

需要对 shell 脚本进行特殊验证

我想创建一个 bash 脚本,该脚本在执行时会有很多选项。

# script.sh  --dry-run --user <parameter1> --pass <parameter2>

我听说过 getopt 选项,但看起来我们只能写其中一个--user or --password--dry-run不能写全部。基本上我想将其--user parameter1作为 input1 和--pass parameter2input2 以及一种特殊情况,其中如果--dry-run存在选项,则仅执行干运行代码而不是生产代码。

#!/bin/bash
user=$1
pass=$2

help() {
    cat<<EOF
Usage : $0 --dry-run --user <user_id> --pass <password>
you can specify --dry-run or --production
EOF
}

[ ${3} ] || help

function dry_run() {
    // --dry-run code 
}

function production() {
   // --production code 
}

我想验证--dry-run,如果选项是--dry-run,则执行函数dry_run(),否则执行production()函数。但是如何编写选项和验证呢?

答案1

如果我明白你在做什么,你可以这样做getopt

#!/bin/bash

PARAMS=$(getopt -l dry-run,production,user:,pass: -n $0 "" -- "$@")
if [ $? != 0 ]; then exit 1; fi
eval set -- "$PARAMS"

dryrun=false

while [ -n "$1" ]; do
    case "$1" in
        --dry-run) dryrun=true; shift;;
        --production) dryrun=false; shift;;
        --user) user="$2"; shift 2;;
        --pass) pass="$2"; shift 2;;
        --) shift;;
        *) exit 1;;
    esac
done

if [ $dryrun = true ]; then
    ...
else
    ...
fi

如果您想禁止同时指定--dry-run--production,或者如果需要--user和,您可以添加更多处理。--password

答案2

您实际上不需要getopt处理脚本长选项。内置getopts函数也可以做到这一点(通常没有子壳)。诀窍是用作-选项。那样--dry-run (例如)变成optvar=-OPTARG=-dry-run。下面是一个功能示例,说明了如何专门针对这种情况执行此操作:

#!/bin/sh
help(){ echo usage; }                       #dummy help
unset   user dryrun pass _o o               #ensure all flag vars are unset
while   getopts :-:u:p:d o              &&  #getopts loop
        o=${o#-}        _o=${o:+$OPTARG}    #empty $o if $o==-
do      case            $o$OPTARG       in  #test concatenated $o$OPTARG
        (u*|-user)      user=${_o:-$2}  ;;  #set $user to $_o or $2
        (p*|-pass)      pass=${_o:-$2}  ;;  #ditto for $pass
        (d*|-dryrun)    o=d dryrun=1    ;;  #no $OPTARG either way - o=d base
        (*)             !  help         ;;  #no usage options met - opt error
        esac || exit                        #quit with error if opt == ! help
        shift "$((!${#o}+(OPTIND-(OPTIND=1))))"  #shift params as they're read
done

这将按原样运行。事实上,我尝试了几种不同的选择可能性。例如:

~/getopts.sh -p-user --user me -uyou -d --dry-run

...当使用#!/bin/sh -xbangline 运行时,将其打印到我的 stderr:

+ unset user dryrun pass _o o
+ getopts :-:u:p:d o
+ o=p _o=-user
+ pass=-user
+ shift 1
+ getopts :-:u:p:d o
+ o= _o=
+ user=me
+ shift 2
+ getopts :-:u:p:d o
+ o=u _o=you
+ user=you
+ shift 1
+ getopts :-:u:p:d o
+ o=d _o=
+ o=d dryrun=1
+ shift 1
+ getopts :-:u:p:d o
+ o= _o=
+ o=d dryrun=1
+ shift 1
+ getopts :-:u:p:d o

完成getopts循环后你可以做...

[ "$((dryrun))" -eq 0 ] && production || dryrun

...如果您已声明production()dryrun()函数。他们将找到指定的$pass和/或$user根据需要分配的任何命令行值。如果其中任何一个尚未在命令行上声明,您可以考虑像这样引用它们:

echo "${user=default_username}" "${pass=default_password}"

...只是为了覆盖您的所有基地。

相关内容