cat >/tmp/demo-space-separated.sh <<'EOF'#!/bin/bash
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; docase $1 in-e|--extension)EXTENSION="$2"shift # past argumentshift # past value;;-s|--searchpath)SEARCHPATH="$2"shift # past argumentshift # past value;;--default)DEFAULT=YESshift # past argument;;-*|--*)echo "Unknown option $1"exit 1;;*)POSITIONAL_ARGS+=("$1") # save positional argshift # past argument;;esacdone
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
echo "FILE EXTENSION = ${EXTENSION}"echo "SEARCH PATH = ${SEARCHPATH}"echo "DEFAULT = ${DEFAULT}"echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l)
if [[ -n $1 ]]; thenecho "Last line of file specified as non-opt/last argument:"tail -1 "$1"fiEOF
chmod +x /tmp/demo-space-separated.sh
/tmp/demo-space-separated.sh -e conf -s /etc /etc/hosts
复制粘贴上面的块的输出
FILE EXTENSION = confSEARCH PATH = /etcDEFAULT =Number files in SEARCH PATH with EXTENSION: 14Last line of file specified as non-opt/last argument:#93.184.216.34 example.com
cat >/tmp/demo-equals-separated.sh <<'EOF'#!/bin/bash
for i in "$@"; docase $i in-e=*|--extension=*)EXTENSION="${i#*=}"shift # past argument=value;;-s=*|--searchpath=*)SEARCHPATH="${i#*=}"shift # past argument=value;;--default)DEFAULT=YESshift # past argument with no value;;-*|--*)echo "Unknown option $i"exit 1;;*);;esacdone
echo "FILE EXTENSION = ${EXTENSION}"echo "SEARCH PATH = ${SEARCHPATH}"echo "DEFAULT = ${DEFAULT}"echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l)
if [[ -n $1 ]]; thenecho "Last line of file specified as non-opt/last argument:"tail -1 $1fiEOF
chmod +x /tmp/demo-equals-separated.sh
/tmp/demo-equals-separated.sh -e=conf -s=/etc /etc/hosts
复制粘贴上面的块的输出
FILE EXTENSION = confSEARCH PATH = /etcDEFAULT =Number files in SEARCH PATH with EXTENSION: 14Last line of file specified as non-opt/last argument:#93.184.216.34 example.com
#!/bin/bash# --- set the value, if there is inputs, override the defaults.
HOME_FOLDER="${HOME}/owned_id_checker"SERVER_FILE_LIST="${HOME_FOLDER}/server_list.txt"
while [[ $# > 1 ]]dokey="$1"shift
case $key in-i|--inputlist)SERVER_FILE_LIST="$1"shift;;esacdone
echo "SERVER LIST = ${SERVER_FILE_LIST}"
#!/usr/bin/env bash
# NOTICE: Uncomment if your script depends on bashisms.#if [ -z "$BASH_VERSION" ]; then bash $0 $@ ; exit $? ; fi
echo "Before"for i ; do echo - $i ; done
# Code template for parsing command line parameters using only portable shell# code, while handling both long and short params, handling '-f file' and# '-f=file' style param data and also capturing non-parameters to be inserted# back into the shell positional parameters.
while [ -n "$1" ]; do# Copy so we can modify it (can't modify $1)OPT="$1"# Detect argument terminationif [ x"$OPT" = x"--" ]; thenshiftfor OPT ; doREMAINS="$REMAINS \"$OPT\""donebreakfi# Parse current optwhile [ x"$OPT" != x"-" ] ; docase "$OPT" in# Handle --flag=value opts like this-c=* | --config=* )CONFIGFILE="${OPT#*=}"shift;;# and --flag value opts like this-c* | --config )CONFIGFILE="$2"shift;;-f* | --force )FORCE=true;;-r* | --retry )RETRY=true;;# Anything unknown is recorded for later* )REMAINS="$REMAINS \"$OPT\""break;;esac# Check for multiple short options# NOTICE: be sure to update this pattern to match valid optionsNEXTOPT="${OPT#-[cfr]}" # try removing single short optif [ x"$OPT" != x"$NEXTOPT" ] ; thenOPT="-$NEXTOPT" # multiple short opts, keep goingelsebreak # long form, exit inner loopfidone# Done with that param. move to nextshiftdone# Set the non-parameters back into the positional parameters ($1 $2 ..)eval set -- $REMAINS
echo -e "After: \n configfile='$CONFIGFILE' \n force='$FORCE' \n retry='$RETRY' \n remains='$REMAINS'"for i ; do echo - $i ; done
./script --arg1=value1 --arg2 value2 --shouldClean
# parse the arguments.COUNTER=0ARGS=("$@")while [ $COUNTER -lt $# ]doarg=${ARGS[$COUNTER]}let COUNTER=COUNTER+1nextArg=${ARGS[$COUNTER]}
if [[ $skipNext -eq 1 ]]; thenecho "Skipping"skipNext=0continuefi
argKey=""argVal=""if [[ "$arg" =~ ^\- ]]; then# if the format is: -key=valueif [[ "$arg" =~ \= ]]; thenargVal=$(echo "$arg" | cut -d'=' -f2)argKey=$(echo "$arg" | cut -d'=' -f1)skipNext=0
# if the format is: -key valueelif [[ ! "$nextArg" =~ ^\- ]]; thenargKey="$arg"argVal="$nextArg"skipNext=1
# if the format is: -key (a boolean flag)elif [[ "$nextArg" =~ ^\- ]] || [[ -z "$nextArg" ]]; thenargKey="$arg"argVal=""skipNext=0fi# if the format has not flag, just a value.elseargKey=""argVal="$arg"skipNext=0fi
case "$argKey" in--source-scmurl)SOURCE_URL="$argVal";;--dest-scmurl)DEST_URL="$argVal";;--version-num)VERSION_NUM="$argVal";;-c|--clean)CLEAN_BEFORE_START="1";;-h|--help|-help|--h)showUsageexit;;esacdone
verbose: y, force: y, debug: y, in: ./foo/bar/someFile, out: /fizz/someOtherFile
以下myscript
#!/bin/bash# More safety, by turning some bugs into errors.# Without `errexit` you don’t need ! and can replace# ${PIPESTATUS[0]} with a simple $?, but I prefer safety.set -o errexit -o pipefail -o noclobber -o nounset
# -allow a command to fail with !’s side effect on errexit# -use return value from ${PIPESTATUS[0]}, because ! hosed $?! getopt --test > /dev/nullif [[ ${PIPESTATUS[0]} -ne 4 ]]; thenecho 'I’m sorry, `getopt --test` failed in this environment.'exit 1fi
# option --output/-o requires 1 argumentLONGOPTS=debug,force,output:,verboseOPTIONS=dfo:v
# -regarding ! and PIPESTATUS see above# -temporarily store output to be able to check for errors# -activate quoting/enhanced mode (e.g. by writing out “--options”)# -pass arguments only via -- "$@" to separate them correctly! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@")if [[ ${PIPESTATUS[0]} -ne 0 ]]; then# e.g. return value is 1# then getopt has complained about wrong arguments to stdoutexit 2fi# read getopt’s output this way to handle the quoting right:eval set -- "$PARSED"
d=n f=n v=n outFile=-# now enjoy the options in order and nicely split until we see --while true; docase "$1" in-d|--debug)d=yshift;;-f|--force)f=yshift;;-v|--verbose)v=yshift;;-o|--output)outFile="$2"shift 2;;--)shiftbreak;;*)echo "Programming error"exit 3;;esacdone
# handle non-option argumentsif [[ $# -ne 1 ]]; thenecho "$0: A single input file is required."exit 4fi
echo "verbose: $v, force: $f, debug: $d, in: $1, out: $outFile"
1增强的getope可在大多数“bash-system”上使用,包括Cygwin;在OS X上尝试brew安装gnu-getop或sudo port install getopt 2 POSIXexec()约定没有可靠的方法在命令行参数中传递二进制NULL;这些字节过早地结束了参数 31997年或之前发布的第一个版本(我只追踪到1997年)
while [[ $# > 0 ]]dokey="$1"while [[ ${key+x} ]]docase $key in-s*|--stage)STAGE="$2"shift # option has parameter;;-w*|--workfolder)workfolder="$2"shift # option has parameter;;-e=*)EXAMPLE="${key#*=}"break # option has been fully handled;;*)# unknown optionecho Unknown option: $key #1>&2exit 10 # either this: my preferred way to handle unknown optionsbreak # or this: do this to signal the option has been handled (if exit isn't used);;esac# prepare for next option in this key, if any[[ "$key" = -? || "$key" == --* ]] && unset key || key="${key/#-?/-}"doneshift # option(s) fully processed, proceed to next input argumentdone
#!/bin/sh
echoecho "POSIX-compliant getopt(s)-free old-style-supporting option parser from phk@[se.unix]"echo
print_usage() {echo "Usage:
$0 {a|b|c} [ARG...]
Options:
--aaa-0-args-aOption without arguments.
--bbb-1-args ARG-b ARGOption with one argument.
--ccc-2-args ARG1 ARG2-c ARG1 ARG2Option with two arguments.
" >&2}
if [ $# -le 0 ]; thenprint_usageexit 1fi
opt=while :; do
if [ $# -le 0 ]; then
# no parameters remaining -> end option parsingbreak
elif [ ! "$opt" ]; then
# we are at the beginning of a fresh block# remove optional leading hyphen and strip trailing whitespacesopt=$(echo "$1" | sed 's/^-\?\([a-zA-Z0-9\?-]*\)/\1/')
fi
# get the first character -> check whether long optionfirst_chr=$(echo "$opt" | awk '{print substr($1, 1, 1)}')[ "$first_chr" = - ] && long_option=T || long_option=F
# note to write the options here with a leading hyphen less# also do not forget to end short options with a starcase $opt in
-)
# end of optionsshiftbreak;;
a*|-aaa-0-args)
echo "Option AAA activated!";;
b*|-bbb-1-args)
if [ "$2" ]; thenecho "Option BBB with argument '$2' activated!"shiftelseecho "BBB parameters incomplete!" >&2print_usageexit 1fi;;
c*|-ccc-2-args)
if [ "$2" ] && [ "$3" ]; thenecho "Option CCC with arguments '$2' and '$3' activated!"shift 2elseecho "CCC parameters incomplete!" >&2print_usageexit 1fi;;
h*|\?*|-help)
print_usageexit 0;;
*)
if [ "$long_option" = T ]; thenopt=$(echo "$opt" | awk '{print substr($1, 2)}')elseopt=$first_chrfiprintf 'Error: Unknown option: "%s"\n' "$opt" >&2print_usageexit 1;;
esac
if [ "$long_option" = T ]; then
# if we had a long option then we are going to get a new block nextshiftopt=
else
# if we had a short option then just move to the next characteropt=$(echo "$opt" | awk '{print substr($1, 2)}')
# if block is now empty then shift to the next one[ "$opt" ] || shift
fi
done
echo "Doing something..."
exit 0
#!/bin/bash
# Universal Bash parameter parsing# Parse equal sign separated params into named local variables# Standalone named parameter value will equal its param name (--force creates variable $force=="force")# Parses multi-valued named params into an array (--path=path1 --path=path2 creates ${path[*]} array)# Puts un-named params as-is into ${ARGV[*]} array# Additionally puts all named params as-is into ${ARGN[*]} array# Additionally puts all standalone "option" params as-is into ${ARGO[*]} array# @author Oleksii Chekulaiev# @version v1.4.1 (Jul-27-2018)parse_params (){local existing_namedlocal ARGV=() # un-named paramslocal ARGN=() # named paramslocal ARGO=() # options (--params)echo "local ARGV=(); local ARGN=(); local ARGO=();"while [[ "$1" != "" ]]; do# Escape asterisk to prevent bash asterisk expansion, and quotes to prevent string breakage_escaped=${1/\*/\'\"*\"\'}_escaped=${_escaped//\'/\\\'}_escaped=${_escaped//\"/\\\"}# If equals delimited named parameternonspace="[^[:space:]]"if [[ "$1" =~ ^${nonspace}${nonspace}*=..* ]]; then# Add to named parameters arrayecho "ARGN+=('$_escaped');"# key is part before first =local _key=$(echo "$1" | cut -d = -f 1)# Just add as non-named when key is empty or contains spaceif [[ "$_key" == "" || "$_key" =~ " " ]]; thenecho "ARGV+=('$_escaped');"shiftcontinuefi# val is everything after key and = (protect from param==value error)local _val="${1/$_key=}"# remove dashes from key name_key=${_key//\-}# skip when key is empty# search for existing parameter nameif (echo "$existing_named" | grep "\b$_key\b" >/dev/null); then# if name already exists then it's a multi-value named parameter# re-declare it as an array if neededif ! (declare -p _key 2> /dev/null | grep -q 'declare \-a'); thenecho "$_key=(\"\$$_key\");"fi# append new valueecho "$_key+=('$_val');"else# single-value named parameterecho "local $_key='$_val';"existing_named=" $_key"fi# If standalone named parameterelif [[ "$1" =~ ^\-${nonspace}+ ]]; then# remove dasheslocal _key=${1//\-}# Just add as non-named when key is empty or contains spaceif [[ "$_key" == "" || "$_key" =~ " " ]]; thenecho "ARGV+=('$_escaped');"shiftcontinuefi# Add to options arrayecho "ARGO+=('$_escaped');"echo "local $_key=\"$_key\";"# non-named parameterelse# Escape asterisk to prevent bash asterisk expansion_escaped=${1/\*/\'\"*\"\'}echo "ARGV+=('$_escaped');"fishiftdone}
#--------------------------- DEMO OF THE USAGE -------------------------------
show_use (){eval $(parse_params "$@")# --echo "${ARGV[0]}" # print first unnamed paramecho "${ARGV[1]}" # print second unnamed paramecho "${ARGN[0]}" # print first named paramecho "${ARG0[0]}" # print first option param (--force)echo "$anyparam" # print --anyparam valueecho "$k" # print k=5 valueecho "${multivalue[0]}" # print first value of multi-valueecho "${multivalue[1]}" # print second value of multi-value[[ "$force" == "force" ]] && echo "\$force is set so let the force be with you"}
show_use "param 1" --anyparam="my value" param2 k=5 --force --multi-value=test1 --multi-value=test2
#!/usr/bin/env bash#shebang.iovalidflags="rate time number"count=1for arg in $@domatch=0argval=$1for flag in $validflagsdosflag="-"$flagif [ "$argval" == "$sflag" ]thendeclare $flag=$2match=1fidoneif [ "$match" == "1" ]thenshift 2elseleftovers=$(echo $leftovers $argval)shiftficount=$(($count+1))done#Cleanup then restore the leftoversshift $#set -- $leftovers
带有内置回声演示的详细版本:
#!/usr/bin/env bash#shebang.iorate=30time=30number=30echo "all args$@"validflags="rate time number"count=1for arg in $@domatch=0argval=$1# argval=$(echo $@ | cut -d ' ' -f$count)for flag in $validflagsdosflag="-"$flagif [ "$argval" == "$sflag" ]thendeclare $flag=$2match=1fidoneif [ "$match" == "1" ]thenshift 2elseleftovers=$(echo $leftovers $argval)shiftficount=$(($count+1))done
#Cleanup then restore the leftoversecho "pre final clear args:$@"shift $#echo "post final clear args:$@"set -- $leftoversecho "all post set args:$@"echo arg1: $1 arg2: $2
echo leftovers: $leftoversecho rate $rate time $time number $number
最后一个,如果传递无效参数,则此错误。
#!/usr/bin/env bash#shebang.iorate=30time=30number=30validflags="rate time number"count=1for arg in $@doargval=$1match=0if [ "${argval:0:1}" == "-" ]thenfor flag in $validflagsdosflag="-"$flagif [ "$argval" == "$sflag" ]thendeclare $flag=$2match=1fidoneif [ "$match" == "0" ]thenecho "Bad argument: $argval"exit 1fishift 2elseleftovers=$(echo $leftovers $argval)shiftficount=$(($count+1))done#Cleanup then restore the leftoversshift $#set -- $leftoversecho rate $rate time $time number $numberecho leftovers: $leftovers
#!/usr/bin/env bash
# usage functionfunction usage(){cat << HEREDOC
Usage: $progname [--num NUM] [--time TIME_STR] [--verbose] [--dry-run]
optional arguments:-h, --help show this help message and exit-n, --num NUM pass in a number-t, --time TIME_STR pass in a time string-v, --verbose increase the verbosity of the bash script--dry-run do a dry run, dont change any files
HEREDOC}
# initialize variablesprogname=$(basename $0)verbose=0dryrun=0num_str=time_str=
# use getopt and store the output into $OPTS# note the use of -o for the short options, --long for the long name options# and a : for any option that takes a parameterOPTS=$(getopt -o "hn:t:v" --long "help,num:,time:,verbose,dry-run" -n "$progname" -- "$@")if [ $? != 0 ] ; then echo "Error in command line arguments." >&2 ; usage; exit 1 ; fieval set -- "$OPTS"
while true; do# uncomment the next line to see how shift is working# echo "\$1:\"$1\" \$2:\"$2\""case "$1" in-h | --help ) usage; exit; ;;-n | --num ) num_str="$2"; shift 2 ;;-t | --time ) time_str="$2"; shift 2 ;;--dry-run ) dryrun=1; shift ;;-v | --verbose ) verbose=$((verbose + 1)); shift ;;-- ) shift; break ;;* ) break ;;esacdone
if (( $verbose > 0 )); then
# print out all the parameters we read incat <<EOMnum=$num_strtime=$time_strverbose=$verbosedryrun=$dryrunEOMfi
# The rest of your script below
# As long as there is at least one more argument, keep loopingwhile [[ $# -gt 0 ]]; dokey="$1"case "$key" in# This is a flag type option. Will catch either -f or --foo-f|--foo)FOO=1;;# Also a flag type option. Will catch either -b or --bar-b|--bar)BAR=1;;# This is an arg value type option. Will catch -o value or --output-file value-o|--output-file)shift # past the key and to the valueOUTPUTFILE="$1";;# This is an arg=value type option. Will catch -o=value or --output-file=value-o=*|--output-file=*)# No need to shift here since the value is part of the same stringOUTPUTFILE="${key#*=}";;*)# Do whatever you want with extra optionsecho "Unknown option '$key'";;esac# Shift after checking all the cases to get the next optionshiftdone
#!/bin/bash -ei
# load the library. bashopts.sh
# Enable backtrace dusplay on errortrap 'bashopts_exit_handle' ERR
# Initialize the librarybashopts_setup -n "$0" -d "This is myapp tool description displayed on help message" -s "$HOME/.config/myapprc"
# Declare the optionsbashopts_declare -n first_name -l first -o f -d "First name" -t string -i -s -rbashopts_declare -n last_name -l last -o l -d "Last name" -t string -i -s -rbashopts_declare -n display_name -l display-name -t string -d "Display name" -e "\$first_name \$last_name"bashopts_declare -n age -l number -d "Age" -t numberbashopts_declare -n email_list -t string -m add -l email -d "Email adress"
# Parse argumentsbashopts_parse_args "$@"
# Process argumentbashopts_process_args
将给予帮助:
NAME:./example.sh - This is myapp tool description displayed on help message
USAGE:[options and commands] [-- [extra args]]
OPTIONS:-h,--help Display this help-n,--non-interactive true Non interactive mode - [$bashopts_non_interactive] (type:boolean, default:false)-f,--first "John" First name - [$first_name] (type:string, default:"")-l,--last "Smith" Last name - [$last_name] (type:string, default:"")--display-name "John Smith" Display name - [$display_name] (type:string, default:"$first_name $last_name")--number 0 Age - [$age] (type:number, default:0)--email Email adress - [$email_list] (type:string, default:"")
for arg in "$@"dokey=$(echo $arg | cut -f1 -d=)`value=$(echo $arg | cut -f2 -d=)`case "$key" inname|-name) read_name=$value;;id|-id) read_id=$value;;*) echo "I dont know what to do with this"easedone
function myrsync() {
local backup=("${@}") args=(); while [[ $# -gt 0 ]]; do k="$1";case "$k" in---sourceuser|---sourceurl|---targetuser|---targeturl|---file|---exclude|---include)eval "local ${k:3}='${2}'"; shift; shift # Past two arguments;;*) # Unknown optionargs+=("$1"); shift; # Past argument only;;esacdone; set -- "${backup[@]}" # Restore $@
echo "${sourceurl}"}
有几种方法可以解析cmdline参数(例如GNU getopt(不可移植)vs BSD(MacOS)getopt vs getopts)-所有这些都有问题。这个解决方案
是便携式的!
零依赖,只依赖bash内置
允许短期和长期选择
处理空白或同时在选项和参数之间使用=分隔符
支持串联短选项样式-vxf
处理带有可选参数的选项(例如--color vs--color=always),
正确检测并报告未知选项
支持--表示选项结束,并且
与相同功能集的替代方案相比,不需要代码膨胀。即简洁,因此更易于维护
示例:任何
# flag-f--foo
# option with required argument-b"Hello World"-b "Hello World"--bar "Hello World"--bar="Hello World"
# option with optional argument--baz--baz="Optional Hello"
#!/usr/bin/env bash
usage() {cat - >&2 <<EOFNAMEprogram-name.sh - Brief description
SYNOPSISprogram-name.sh [-h|--help]program-name.sh [-f|--foo][-b|--bar <arg>][--baz[=<arg>]][--]FILE ...
REQUIRED ARGUMENTSFILE ...input files
OPTIONS-h, --helpPrints this and exits
-f, --fooA flag option
-b, --bar <arg>Option requiring an argument <arg>
--baz[=<arg>]Option that has an optional argument <arg>. If <arg>is not specified, defaults to 'DEFAULT'--Specify end of options; useful if the first non optionargument starts with a hyphen
EOF}
fatal() {for i; doecho -e "${i}" >&2doneexit 1}
# For long option processingnext_arg() {if [[ $OPTARG == *=* ]]; then# for cases like '--opt=arg'OPTARG="${OPTARG#*=}"else# for cases like '--opt arg'OPTARG="${args[$OPTIND]}"OPTIND=$((OPTIND + 1))fi}
# ':' means preceding option character expects one argument, except# first ':' which make getopts run in silent mode. We handle errors with# wildcard case catch. Long options are considered as the '-' characteroptspec=":hfb:-:"args=("" "$@") # dummy first element so $1 and $args[1] are alignedwhile getopts "$optspec" optchar; docase "$optchar" inh) usage; exit 0 ;;f) foo=1 ;;b) bar="$OPTARG" ;;-) # long option processingcase "$OPTARG" inhelp)usage; exit 0 ;;foo)foo=1 ;;bar|bar=*) next_argbar="$OPTARG" ;;baz)baz=DEFAULT ;;baz=*) next_argbaz="$OPTARG" ;;-) break ;;*) fatal "Unknown option '--${OPTARG}'" "see '${0} --help' for usage" ;;esac;;*) fatal "Unknown option: '-${OPTARG}'" "See '${0} --help' for usage" ;;esacdone
shift $((OPTIND-1))
if [ "$#" -eq 0 ]; thenfatal "Expected at least one required argument FILE" \"See '${0} --help' for usage"fi
echo "foo=$foo, bar=$bar, baz=$baz, files=${@}"
retval=$?
if [ $retval -ne 0 ]; then# this will manage error messages if# insufficient or extra args are supplied
option_parser_error_msg "$retval"
# This will print the usageprint_usage 'fruit'exit 1fi
现在要检查是否通过了某些选项,
if [ -n "${OPTIONS[-c]}" ]thenecho "-c was passed"
# args can be accessed in a 2D-array-like formatecho "Arg1 to -c = ${ARGS[-c,0]}"echo "Arg2 to -c = ${ARGS[-c,1]}"
fi
$ bash example.sh -n Willy --gender male -a 99Name: WillyAge: 99Gender: maleLocation: chocolate-factory
$ bash example.sh -n Meir --gender male[ERROR] Required argument: age
Usage: bash example.sh -n Willy --gender male -a 99
--person_name | -n [Willy] What is your name?--age | -a [Required]--gender | -g [Required]--location | -l [chocolate-factory] insert your location
$ bash example.sh -h
Usage: bash example.sh -n Willy --gender male -a 99--person_name | -n [Willy] What is your name?--age | -a [Required]--gender | -g [Required]--location | -l [chocolate-factory] insert your location
#!/bin/bashset -e
function parse() {for arg in "$@"; do # transform long options to short onesshiftcase "$arg" in"--name") set -- "$@" "-n" ;;"--verbose") set -- "$@" "-v" ;;*) set -- "$@" "$arg"esacdone
while getopts "n:v" optname # left to ":" are flags that expect a value, right to the ":" are flags that expect nothingdocase "$optname" in"n") name=${OPTARG} ;;"v") verbose=true ;;esacdoneshift "$((OPTIND-1))" # shift out all the already processed options}
parse "$@"echo "hello $name"if [ ! -z $verbose ]; then echo 'nice to meet you!'; fi
用法:
$ ./parse.shhello$ ./parse.sh -n YOUR_NAMEhello YOUR_NAME$ ./parse.sh -n YOUR_NAME -vhello YOUR_NAMEnice to meet you!$ ./parse.sh -v -n YOUR_NAMEhello YOUR_NAMEnice to meet you!$ ./parse.sh -vhellonice to meet you!