本文翻译自:An example of how to use getopts in bash

I want to call myscript file in this way: 我想以这种方式调用myscript文件:

$ ./myscript -s 45 -p any_string

or 要么

$ ./myscript -h >>> should display help
$ ./myscript    >>> should display help

My requirements are: 我的要求是:

  • getopt here to get the input arguments getopt这里获取输入参数
  • check that -s exists, if not return error 检查-s存在,如果没有返回错误
  • check that the value after the -s is 45 or 90 检查-s之后的值是45还是90
  • check that the -p exists and there is an input string after 检查-p存在,之后是否有输入字符串
  • if the user enters ./myscript -h or just ./myscript then display help 如果用户输入./myscript -h或只是./myscript则显示帮助

I tried so far this code: 我到目前为止尝试了这段代码:

#!/bin/bash
while getopts "h:s:" arg; docase $arg inh)echo "usage" ;;s)strength=$OPTARGecho $strength;;esac
done

But with that code I get errors. 但是使用该代码我会收到错误。 How to do it with Bash and getopt ? 如何用Bash和getopt做到这一点?


#1楼

参考:https://stackoom.com/question/17A0l/一个如何在bash中使用getopts的例子


#2楼

The example packaged with getopt (my distro put it in /usr/share/getopt/getopt-parse.bash ) looks like it covers all of your cases: getopt一起打包的示例(我的发行版将它放在/usr/share/getopt/getopt-parse.bash )看起来像是涵盖了所有情况:

#!/bin/bash# A small example program for using the new getopt(1) program.
# This program will only work with bash(1)
# An similar program using the tcsh(1) script language can be found
# as parse.tcsh# Example input and output (from the bash prompt):
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
# Option a
# Option c, no argument
# Option c, argument `more'
# Option b, argument ` very long '
# Remaining arguments:
# --> `par1'
# --> `another arg'
# --> `wow!*\?'# Note that we use `"$@"' to let each command-line parameter expand to a
# separate word. The quotes around `$@' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \-n 'example.bash' -- "$@"`if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"while true ; docase "$1" in-a|--a-long) echo "Option a" ; shift ;;-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;-c|--c-long) # c has an optional argument. As we are in quoted mode,# an empty parameter will be generated if its optional# argument is not found.case "$2" in"") echo "Option c, no argument"; shift 2 ;;*)  echo "Option c, argument \`$2'" ; shift 2 ;;esac ;;--) shift ; break ;;*) echo "Internal error!" ; exit 1 ;;esac
done
echo "Remaining arguments:"
for arg do echo '--> '"\`$arg'" ; done

#3楼

#!/bin/bashusage() { echo "Usage: $0 [-s <45|90>] [-p <string>]" 1>&2; exit 1; }while getopts ":s:p:" o; docase "${o}" ins)s=${OPTARG}((s == 45 || s == 90)) || usage;;p)p=${OPTARG};;*)usage;;esac
done
shift $((OPTIND-1))if [ -z "${s}" ] || [ -z "${p}" ]; thenusage
fiecho "s = ${s}"
echo "p = ${p}"

Example runs: 示例运行:

$ ./myscript.sh
Usage: ./myscript.sh [-s <45|90>] [-p <string>]$ ./myscript.sh -h
Usage: ./myscript.sh [-s <45|90>] [-p <string>]$ ./myscript.sh -s "" -p ""
Usage: ./myscript.sh [-s <45|90>] [-p <string>]$ ./myscript.sh -s 10 -p foo
Usage: ./myscript.sh [-s <45|90>] [-p <string>]$ ./myscript.sh -s 45 -p foo
s = 45
p = foo$ ./myscript.sh -s 90 -p bar
s = 90
p = bar

#4楼

I know that this is already answered, but for the record and for anyone with the same requeriments as me I decided to post this related answer. 我知道这已经得到了回答,但是对于记录和任何与我有同样要求的人我决定发布这个相关的答案。 The code is flooded with comments to explain the code. 代码充斥着注释来解释代码。

Updated answer: 更新的答案:

Save the file as getopt.sh : 将文件另存为getopt.sh

#!/bin/bashfunction get_variable_name_for_option {local OPT_DESC=${1}local OPTION=${2}local VAR=$(echo ${OPT_DESC} | sed -e "s/.*\[\?-${OPTION} \([A-Z_]\+\).*/\1/g" -e "s/.*\[\?-\(${OPTION}\).*/\1FLAG/g")if [[ "${VAR}" == "${1}" ]]; thenecho ""elseecho ${VAR}fi
}function parse_options {local OPT_DESC=${1}local INPUT=$(get_input_for_getopts "${OPT_DESC}")shiftwhile getopts ${INPUT} OPTION ${@};do[ ${OPTION} == "?" ] && usageVARNAME=$(get_variable_name_for_option "${OPT_DESC}" "${OPTION}")[ "${VARNAME}" != "" ] && eval "${VARNAME}=${OPTARG:-true}" # && printf "\t%s\n" "* Declaring ${VARNAME}=${!VARNAME} -- OPTIONS='$OPTION'"donecheck_for_required "${OPT_DESC}"}function check_for_required {local OPT_DESC=${1}local REQUIRED=$(get_required "${OPT_DESC}" | sed -e "s/\://g")while test -n "${REQUIRED}"; doOPTION=${REQUIRED:0:1}VARNAME=$(get_variable_name_for_option "${OPT_DESC}" "${OPTION}")[ -z "${!VARNAME}" ] && printf "ERROR: %s\n" "Option -${OPTION} must been set." && usageREQUIRED=${REQUIRED:1}done
}function get_input_for_getopts {local OPT_DESC=${1}echo ${OPT_DESC} | sed -e "s/\([a-zA-Z]\) [A-Z_]\+/\1:/g" -e "s/[][ -]//g"
}function get_optional {local OPT_DESC=${1}echo ${OPT_DESC} | sed -e "s/[^[]*\(\[[^]]*\]\)[^[]*/\1/g" -e "s/\([a-zA-Z]\) [A-Z_]\+/\1:/g" -e "s/[][ -]//g"
}function get_required {local OPT_DESC=${1}echo ${OPT_DESC} | sed -e "s/\([a-zA-Z]\) [A-Z_]\+/\1:/g" -e "s/\[[^[]*\]//g" -e "s/[][ -]//g"
}function usage {printf "Usage:\n\t%s\n" "${0} ${OPT_DESC}"exit 10
}

Then you can use it like this: 然后你可以像这样使用它:

#!/bin/bash
#
# [ and ] defines optional arguments
## location to getopts.sh file
source ./getopt.sh
USAGE="-u USER -d DATABASE -p PASS -s SID [ -a START_DATE_TIME ]"
parse_options "${USAGE}" ${@}echo ${USER}
echo ${START_DATE_TIME}

Old answer: 老答案:

I recently needed to use a generic approach. 我最近需要使用通用方法。 I came across with this solution: 我遇到了这个解决方案:

#!/bin/bash
# Option Description:
# -------------------
#
# Option description is based on getopts bash builtin. The description adds a variable name feature to be used
# on future checks for required or optional values.
# The option description adds "=>VARIABLE_NAME" string. Variable name should be UPPERCASE. Valid characters
# are [A-Z_]*.
#
# A option description example:
#   OPT_DESC="a:=>A_VARIABLE|b:=>B_VARIABLE|c=>C_VARIABLE"
#
# -a option will require a value (the colon means that) and should be saved in variable A_VARIABLE.
# "|" is used to separate options description.
# -b option rule applies the same as -a.
# -c option doesn't require a value (the colon absense means that) and its existence should be set in C_VARIABLE
#
#   ~$ echo get_options ${OPT_DESC}
#   a:b:c
#   ~$
## Required options
REQUIRED_DESC="a:=>REQ_A_VAR_VALUE|B:=>REQ_B_VAR_VALUE|c=>REQ_C_VAR_FLAG"# Optional options (duh)
OPTIONAL_DESC="P:=>OPT_P_VAR_VALUE|r=>OPT_R_VAR_FLAG"function usage {IFS="|"printf "%s" ${0}for i in ${REQUIRED_DESC};doVARNAME=$(echo $i | sed -e "s/.*=>//g")printf " %s" "-${i:0:1} $VARNAME"donefor i in ${OPTIONAL_DESC};doVARNAME=$(echo $i | sed -e "s/.*=>//g")printf " %s" "[-${i:0:1} $VARNAME]"doneprintf "\n"unset IFSexit
}# Auxiliary function that returns options characters to be passed
# into 'getopts' from a option description.
# Arguments:
#   $1: The options description (SEE TOP)
#
# Example:
#   OPT_DESC="h:=>H_VAR|f:=>F_VAR|P=>P_VAR|W=>W_VAR"
#   OPTIONS=$(get_options ${OPT_DESC})
#   echo "${OPTIONS}"
#
# Output:
#   "h:f:PW"
function get_options {echo ${1} | sed -e "s/\([a-zA-Z]\:\?\)=>[A-Z_]*|\?/\1/g"
}# Auxiliary function that returns all variable names separated by '|'
# Arguments:
#       $1: The options description (SEE TOP)
#
# Example:
#       OPT_DESC="h:=>H_VAR|f:=>F_VAR|P=>P_VAR|W=>W_VAR"
#       VARNAMES=$(get_values ${OPT_DESC})
#       echo "${VARNAMES}"
#
# Output:
#       "H_VAR|F_VAR|P_VAR|W_VAR"
function get_variables {echo ${1} | sed -e "s/[a-zA-Z]\:\?=>\([^|]*\)/\1/g"
}# Auxiliary function that returns the variable name based on the
# option passed by.
# Arguments:
#   $1: The options description (SEE TOP)
#   $2: The option which the variable name wants to be retrieved
#
# Example:
#   OPT_DESC="h:=>H_VAR|f:=>F_VAR|P=>P_VAR|W=>W_VAR"
#   H_VAR=$(get_variable_name ${OPT_DESC} "h")
#   echo "${H_VAR}"
#
# Output:
#   "H_VAR"
function get_variable_name {VAR=$(echo ${1} | sed -e "s/.*${2}\:\?=>\([^|]*\).*/\1/g")if [[ ${VAR} == ${1} ]]; thenecho ""elseecho ${VAR}fi
}# Gets the required options from the required description
REQUIRED=$(get_options ${REQUIRED_DESC})# Gets the optional options (duh) from the optional description
OPTIONAL=$(get_options ${OPTIONAL_DESC})# or... $(get_options "${OPTIONAL_DESC}|${REQUIRED_DESC}")# The colon at starts instructs getopts to remain silent
while getopts ":${REQUIRED}${OPTIONAL}" OPTION
do[[ ${OPTION} == ":" ]] && usageVAR=$(get_variable_name "${REQUIRED_DESC}|${OPTIONAL_DESC}" ${OPTION})[[ -n ${VAR} ]] && eval "$VAR=${OPTARG}"
doneshift $(($OPTIND - 1))# Checks for required options. Report an error and exits if
# required options are missing.# Using function version ...
VARS=$(get_variables ${REQUIRED_DESC})
IFS="|"
for VARNAME in $VARS;
do[[ -v ${VARNAME} ]] || usage
done
unset IFS# ... or using IFS Version (no function)
OLDIFS=${IFS}
IFS="|"
for i in ${REQUIRED_DESC};
doVARNAME=$(echo $i | sed -e "s/.*=>//g")[[ -v ${VARNAME} ]] || usageprintf "%s %s %s\n" "-${i:0:1}" "${!VARNAME:=present}" "${VARNAME}"
done
IFS=${OLDIFS}

I didn't test this roughly, so I could have some bugs in there. 我没有粗略测试,所以我可能会有一些错误。


#5楼

The problem with the original code is that: 原始代码的问题是:

  • h: expects parameter where it shouldn't, so change it into just h (without colon) h:期望参数不应该,所以将其改为h (不带冒号)
  • to expect -p any_string , you need to add p: to the argument list 期望-p any_string ,你需要将p:添加到参数列表中

The basic syntax of getopts is (see: man bash ): getopts的基本语法是(参见: man bash ):

getopts OPTSTRING VARNAME [ARGS...]

where: 哪里:

  • OPTSTRING is string with list of expected arguments, OPTSTRING是带有预期参数列表的字符串,

    • h - check for option -h without parameters; h - 检查选项-h 不带参数; gives error on unsupported options; 在不支持的选项上给出错误;
    • h: - check for option -h with parameter; h: - 参数检查选项-h ; gives errors on unsupported options; 在不支持的选项上出错;
    • abc - check for options -a , -b , -c ; abc - 检查选项-a-b-c ; gives errors on unsupported options; 给出了支持的选项错误;
    • :abc - check for options -a , -b , -c ; :abc - 检查选项-a-b-c ; silences errors on unsupported options; 在不支持的选项上沉默错误;

      Notes: In other words, colon in front of options allows you handle the errors in your code. 注意:换句话说,选项前面的冒号允许您处理代码中的错误。 Variable will contain ? 变量将包含? in the case of unsupported option, : in the case of missing value. 在不支持的选项的情况下, :在缺少值的情况下。

  • OPTARG - is set to current argument value, OPTARG - 设置为当前参数值,

  • OPTERR - indicates if Bash should display error messages. OPTERR - 指示Bash是否应显示错误消息。

So the code can be: 所以代码可以是:

#!/usr/bin/env bash
usage() { echo "$0 usage:" && grep " .)\ #" $0; exit 0; }
[ $# -eq 0 ] && usage
while getopts ":hs:p:" arg; docase $arg inp) # Specify p value.echo "p is ${OPTARG}";;s) # Specify strength, either 45 or 90.strength=${OPTARG}[ $strength -eq 45 -o $strength -eq 90 ] \&& echo "Strength is $strength." \|| echo "Strength needs to be either 45 or 90, $strength found instead.";;h | *) # Display help.usageexit 0;;esac
done

Example usage: 用法示例:

$ ./foo.sh
./foo.sh usage:p) # Specify p value.s) # Specify strength, either 45 or 90.h | *) # Display help.
$ ./foo.sh -s 123 -p any_string
Strength needs to be either 45 or 90, 123 found instead.
p is any_string
$ ./foo.sh -s 90 -p any_string
Strength is 90.
p is any_string

See: Small getopts tutorial at Bash Hackers Wiki 请参阅:Bash Hackers Wiki上的Small getopts教程


#6楼

POSIX 7 example POSIX 7示例

It is also worth checking the example from the standard: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html 还值得查看标准中的示例: http : //pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html

aflag=
bflag=
while getopts ab: name
docase $name ina)    aflag=1;;b)    bflag=1bval="$OPTARG";;?)   printf "Usage: %s: [-a] [-b value] args\n" $0exit 2;;esac
done
if [ ! -z "$aflag" ]; thenprintf "Option -a specified\n"
fi
if [ ! -z "$bflag" ]; thenprintf 'Option -b "%s" specified\n' "$bval"
fi
shift $(($OPTIND - 1))
printf "Remaining arguments are: %s\n" "$*"

And then we can try it out: 然后我们可以尝试一下:

$ sh a.sh
Remaining arguments are:
$ sh a.sh -a
Option -a specified
Remaining arguments are:
$ sh a.sh -b
No arg for -b option
Usage: a.sh: [-a] [-b value] args
$ sh a.sh -b myval
Option -b "myval" specified
Remaining arguments are:
$ sh a.sh -a -b myval
Option -a specified
Option -b "myval" specified
Remaining arguments are:
$ sh a.sh remain
Remaining arguments are: remain
$ sh a.sh -- -a remain
Remaining arguments are: -a remain

Tested in Ubuntu 17.10, sh is dash 0.5.8. 在Ubuntu 17.10中测试, sh是破折号0.5.8。

一个如何在bash中使用getopts的例子相关推荐

  1. 如何在 bash 中使用索引数组

    数组是一种数据结构,表示具有相同数据类型的对象集合.bash shell中支持两种类型的数组:关联数组或索引数组.在本文中,将演示如何在 bash 中使用索引数组.以下使用 shell 示例来说明索引 ...

  2. 如何在 bash 中使用键值字典

    在字典中,字典存储一组键,每个键都有一个与之关联的值.可以使用对应的键在字典中插入.检索或更新值.字典数据结构针对基于键值的快速检索进行了优化,因此通常使用哈希表来实现.在不同的编程语言中,字典通常有 ...

  3. linux shell 递增,如何在 Bash 中对变量递增或者递减

    原标题:如何在 Bash 中对变量递增或者递减 编写 Bash脚本时最常见的算术运算之一是递增和递减变量.这通常在循环中用作计数器,但它也可以在脚本的其他地方出现. 递增和递减意味着分别从数值变量的值 ...

  4. 中查询一个文件夹下文件数量_如何在 Bash 中使用循环 | Linux 中国

    使用循环和查找命令批量自动对多个文件进行一系列的操作.-- Seth Kenlon(作者) 人们希望学习批处理命令的一个普遍原因是要得到批处理强大的功能.如果你希望批量的对文件执行一些指令,构造一个可 ...

  5. 如何在bash中等待多个子进程完成并在任何子进程以代码!= 0结尾时返回退出代码!= 0?

    如何在bash脚本中等待从该脚本派生的多个子进程完成并返回退出代码!= 0,当任何子进程以代码!= 0结尾时? 简单脚本: #!/bin/bash for i in `seq 0 9`; dodoCa ...

  6. 如何在Bash中加入数组元素?

    如果我在Bash中有这样的数组: FOO=( a b c ) 如何用逗号将元素加入? 例如,产生a,b,c . #1楼 重复使用@无关紧要的解决方案,但是通过避免$ {:1}的替换和避免中间变量的使用 ...

  7. 如何在Bash中比较字符串

    如何将变量与字符串进行比较(如果匹配则执行某些操作)? #1楼 要将字符串与通配符进行比较,请使用 if [[ "$stringA" == *$stringB* ]]; then# ...

  8. 如何在Bash中的分隔符上拆分字符串?

    我将此字符串存储在变量中: IN="bla@some.com;john@home.com" 现在我想用拆分字符串; 分隔符,以便我有: ADDR1="bla@some.c ...

  9. bash中的grep函数_如何在Bash中编写函数

    bash中的grep函数 在编程时,实际上是在定义要由计算机执行的过程或例程 . 一个简单的类比将计算机编程与烤面包进行比较:您一次列出了要设置工作环境的成分,然后列出了最终要面包所必须采取的步骤. ...

最新文章

  1. 【项目管理】Scrum内容整理
  2. C/C++隐式类型转换导致的若干问题
  3. f ajax event,f:ajax onevent不能使用预定义函数,但可以使用内联函数
  4. 博弈论——关于Nim游戏和SG函数的几个链接
  5. 初识python之 APP store排行榜 蜘蛛抓取(一)
  6. Maven实战. 1.3Maven与极限编程
  7. 《暗时间》这本书内容丰富,思路明晰,是学习思维方法的好参考书
  8. Python字符串isalnum()
  9. express url跳转(重定向)的实现:res.location() res.redirect()
  10. dubbo接口demo开发
  11. lopatkin俄大神精简中文系统Windows 7 Professional SP1 7601.24540 x64 ZH-CN LITE10
  12. 5道Python数据分析面试题
  13. 阅读《Android 从入门到精通》(10)——单项选择
  14. C++ STL map插入效率优化
  15. not in 与not exists区别
  16. (Emitted value instead of an instance of Error) <swiper-slide v-for=“img in allData.url“>: component
  17. 【Tushare转存SQL】可转债数据(待续)
  18. 【网络原理】一个数据包从发送到接收在网络中经历了那些过程(详细分析)
  19. 1. 神经网络面试题总结
  20. 最有元宇宙“面相“的Discord, 及腾讯/阿里/网易/百度/字跳元宇宙可行性路径分析

热门文章

  1. PostgreSQL B+树索引---页面删除
  2. Android安装apk报错 问题记录
  3. html5网页中的表格教程,javascript程序设计_达内javascript教程-达内web前端培训
  4. 股票指数的四种加权方式
  5. 加权均值滤波matlab,模糊加权均值滤波器
  6. 网络正常连接,浏览器无法打开网页的解决方法
  7. 点网络计算机怎么出现蓝屏,电脑总是出现蓝屏该怎么解决
  8. MDK编译过程及ARM编译工具链
  9. 《新神榜:杨戬》亮点抢先看!追光新神话宇宙再添超燃国风巨作
  10. 鹅长微服务发现与治理巨作PolarisMesh实践-上