如何为标志创建带有可选参数的 bash 脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15524839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 23:28:10  来源:igfitidea点击:

How to create a bash script with optional parameters for a flag

bashshell

提问by ederlf

I'm trying to create a script which will have a flag with optional options. With getopts it's possible to specify a mandatory argument (using a colon) after the flag, but I want to keep it optional.

我正在尝试创建一个脚本,该脚本将有一个带有可选选项的标志。使用 getopts 可以在标志后指定一个强制参数(使用冒号),但我想保持它是可选的。

It will be something like this:

它会是这样的:

./install.sh -a 3

or

或者

./install.sh -a3

where 'a' is the flag and '3' is the optional parameter that follows a.

其中'a'是标志,'3'是a后面的可选参数。

Thanks in advance.

提前致谢。

采纳答案by chepner

The getoptexternal program allows options to have a single optional argument by adding a double-colon to the option name.

getopt外部程序可以选择加入了双冒号的选项名称有一个可选参数。

# Based on a longer example in getopt-parse.bash, included with
# getopt
TEMP=$(getopt -o a:: -- "$@")
eval set -- "$TEMP"
while true ; do
   case "" in
     -a)
        case "" in 
          "") echo "Option a, no argument"; shift 2 ;;
          *) echo "Option a, argument "; shift 2;;
        esac ;;
     --) shift; break ;;
     *) echo "Internal error!"; exit 1 ;;
   esac
done

回答by Dipto

The following is without getoptand it takes an optional argument with the -a flag:

以下是没有的getopt,它需要一个带有 -a 标志的可选参数:

for WORD; do
        case $WORD in
            -a?)  echo "single arg Option"
                SEP=${WORD:2:1}
                echo $SEP
                shift ;;
            -a) echo "split arg Option"
                if [[ ${2:0:1} != "-" && ${2:0:1} != ""]] ; then
                 SEP=
                 shift 2
                 echo "arg present"
                 echo $SEP
                else
                 echo "optional arg omitted"
                fi ;;
            -a*) echo "arg Option"
                SEP=${WORD:2}
                echo $SEP
                shift ;;
            -*) echo "Unrecognized Short Option"
                echo "Unrecognized argument"
            ;;
        esac
done

Other options/flags also can be added easily.

也可以轻松添加其他选项/标志。

回答by Alepac

My solution:

我的解决方案:

#!/bin/bash
count=0
skip=0
flag="no flag"
list=($@) #put args in array
for arg in $@ ; do #iterate over array
    count=$(($count+1)) #update counter
    if [ $skip -eq 1 ]; then #check if we have to skip this args
        skip=0
        continue
    fi
    opt=${arg:0:2} #get only first 2 chars as option
    if [ $opt == "-a" ]; then #check if option equals "-a"
       if [ $opt == $arg ] ; then #check if this is only the option or has a flag
            if [ ${list[$count]:0:1} != "-" ]; then #check if next arg is an option
                skip=1 #skip next arg
                flag=${list[$count]} #use next arg as flag
            fi
       else
            flag=${arg:2} #use chars after "-a" as flag
       fi 
    fi
done

echo $flag

回答by Randy Howard

Use the getopt feature. On most systems, man getoptwill yield documentation for it, and even examples of using it in a script. From the man page on my system:

使用 getopt 功能。在大多数系统上,man getopt会生成它的文档,甚至是在脚本中使用它的示例。从我系统上的手册页:

The following code fragment shows how one might process the arguments for a command that can take the options -a and -b, and the option -o, which requires an argument.

以下代码片段显示了如何处理可以采用选项 -a 和 -b 以及需要参数的选项 -o 的命令的参数。

       args=`getopt abo: $*`
       # you should not use `getopt abo: "$@"` since that would parse
       # the arguments differently from what the set command below does.
       if [ $? != 0 ]
       then
               echo 'Usage: ...'
               exit 2
       fi
       set -- $args
       # You cannot use the set command with a backquoted getopt directly,
       # since the exit code from getopt would be shadowed by those of set,
       # which is zero by definition.
       for i
       do
               case "$i"
               in
                       -a|-b)
                               echo flag $i set; sflags="${i#-}$sflags";
                               shift;;
                       -o)
                               echo oarg is "'""'"; oarg=""; shift;
                               shift;;
                       --)
                               shift; break;;
               esac
       done
       echo single-char flags: "'"$sflags"'"
       echo oarg is "'"$oarg"'"

This code will accept any of the following as equivalent:

此代码将接受以下任何等效项:

       cmd -aoarg file file
       cmd -a -o arg file file
       cmd -oarg -a file file
       cmd -a -oarg -- file file

回答by Xavier S.

In bash there is some implicit variable:

在 bash 中有一些隐式变量:

    $#: contains number of arguments for a called script/function

    
    #!/bin/ksh

    if [ $# -ne 2 ]
    then
        echo "Wrong number of argument - expected 2 : $#"
    else
        echo "Argument list:"
        echo "\t##代码##"
        echo "\t"
        echo "\t"
    fi
: contains names of script/function : contains first argument : contains second argument ... $n: contains n-th argument

For example:

例如:

##代码##