如何在Bash中获取带有标志的参数
我知道我可以很容易地在bash中获得这样的定位参数:如何在Bash中获取带有标志的参数,bash,shell,Bash,Shell,我知道我可以很容易地在bash中获得这样的定位参数: $0或$1 我希望能够使用这样的标志选项来指定每个参数的用途: mysql -u user -h host 通过标志而不是位置获取-u参数值和-h参数值的最佳方法是什么 while test $# -gt 0; do case "$1" in -h|--help) echo "$package - attempt to capture frames" echo " " echo "$packa
$0
或$1
我希望能够使用这样的标志选项来指定每个参数的用途:
mysql -u user -h host
通过标志而不是位置获取
-u参数
值和-h参数
值的最佳方法是什么
while test $# -gt 0; do
case "$1" in
-h|--help)
echo "$package - attempt to capture frames"
echo " "
echo "$package [options] application [arguments]"
echo " "
echo "options:"
echo "-h, --help show brief help"
echo "-a, --action=ACTION specify an action to use"
echo "-o, --output-dir=DIR specify a directory to store output in"
exit 0
;;
-a)
shift
if test $# -gt 0; then
export PROCESS=$1
else
echo "no process specified"
exit 1
fi
shift
;;
--action*)
export PROCESS=`echo $1 | sed -e 's/^[^=]*=//g'`
shift
;;
-o)
shift
if test $# -gt 0; then
export OUTPUT=$1
else
echo "no output dir specified"
exit 1
fi
shift
;;
--output-dir*)
export OUTPUT=`echo $1 | sed -e 's/^[^=]*=//g'`
shift
;;
*)
break
;;
esac
done
重点是:
是参数的数量$#
- while循环查看提供的所有参数,并在case语句中匹配它们的值
- 轮班把第一个带走。可以在case语句内多次移位以获取多个值
function f () {
TEMP=`getopt --long -o "u:h:" "$@"`
eval set -- "$TEMP"
while true ; do
case "$1" in
-u )
user=$2
shift 2
;;
-h )
host=$2
shift 2
;;
*)
break
;;
esac
done;
echo "user = $user, host = $host"
}
f -u myself -h some_host
您的/usr/bin目录中应该有各种示例。此示例使用Bash的内置命令,来自: 注意:如果一个字符后面跟一个冒号(例如,
f:
),则该选项应该有一个参数
用法示例:/script-v-a-b-f文件名
与公认的答案相比,使用getopts有几个优点:
- while条件更具可读性,并显示了可接受的选项
- 清洁守则;不计算参数和移位的数量
- 您可以加入选项(例如
→ <代码>-abc)-a-b-c
但是,一个很大的缺点是它不支持长选项,只支持单字符选项。另一种选择是使用下面的示例,它允许您使用长--image或短-i标记,还允许编译-i=“example.jpg”或separate-i example.jpg传入参数的方法
# declaring a couple of associative arrays
declare -A arguments=();
declare -A variables=();
# declaring an index integer
declare -i index=1;
# any variables you want to use here
# on the left left side is argument label or key (entered at the command line along with it's value)
# on the right side is the variable name the value of these arguments should be mapped to.
# (the examples above show how these are being passed into this script)
variables["-gu"]="git_user";
variables["--git-user"]="git_user";
variables["-gb"]="git_branch";
variables["--git-branch"]="git_branch";
variables["-dbr"]="db_fqdn";
variables["--db-redirect"]="db_fqdn";
variables["-e"]="environment";
variables["--environment"]="environment";
# $@ here represents all arguments passed in
for i in "$@"
do
arguments[$index]=$i;
prev_index="$(expr $index - 1)";
# this if block does something akin to "where $i contains ="
# "%=*" here strips out everything from the = to the end of the argument leaving only the label
if [[ $i == *"="* ]]
then argument_label=${i%=*}
else argument_label=${arguments[$prev_index]}
fi
# this if block only evaluates to true if the argument label exists in the variables array
if [[ -n ${variables[$argument_label]} ]]
then
# dynamically creating variables names using declare
# "#$argument_label=" here strips out the label leaving only the value
if [[ $i == *"="* ]]
then declare ${variables[$argument_label]}=${i#$argument_label=}
else declare ${variables[$argument_label]}=${arguments[$index]}
fi
fi
index=index+1;
done;
# then you could simply use the variables like so:
echo "$git_user";
我认为这可以作为一个简单的例子来说明你想要实现的目标。不需要使用外部工具。Bash内置工具可以为您完成这项工作
function DOSOMETHING {
while test $# -gt 0; do
case "$1" in
-first)
shift
first_argument=$1
shift
;;
-last)
shift
last_argument=$1
shift
;;
*)
echo "$1 is not a recognized flag!"
return 1;
;;
esac
done
echo "First argument : $first_argument";
echo "Last argument : $last_argument";
}
这将允许您使用标志,因此无论您以何种顺序传递参数,都将获得正确的行为
例如:
DOSOMETHING -last "Adios" -first "Hola"
输出:
First argument : Hola
Last argument : Adios
您可以将此函数添加到您的配置文件或将其放入脚本中
谢谢
编辑:
将此文件另存为一个文件,然后作为yourfile.sh-最后一个“Adios”-第一个“Hola”
我在这里最喜欢Robert McMahan的答案,因为它似乎最容易生成可共享的包含文件,供您的任何脚本使用。但是它似乎有一个缺陷,行
if[[-n${variables[$argument\u label]}]
抛出消息,“variables:bad array subscript”。我没有代表发表评论,我怀疑这是正确的“修复”,但将if
包装在if[-n$argument_label]]中;然后
将其清理干净
这是我最后的代码,如果你知道更好的方法,请在Robert的答案中添加注释
包括文件“flags declares.sh”
包括文件“flags arguments.sh”
你的“script.sh”
如果您熟悉Python argparse,并且不介意调用Python来解析bash参数,那么我发现有一段代码非常有用并且非常易于使用,名为argparse bash 示例取自他们的Example.sh脚本:
#!/bin/bash
source $(dirname $0)/argparse.bash || exit 1
argparse "$@" <<EOF || exit 1
parser.add_argument('infile')
parser.add_argument('outfile')
parser.add_argument('-a', '--the-answer', default=42, type=int,
help='Pick a number [default %(default)s]')
parser.add_argument('-d', '--do-the-thing', action='store_true',
default=False, help='store a boolean [default %(default)s]')
parser.add_argument('-m', '--multiple', nargs='+',
help='multiple values allowed')
EOF
echo required infile: "$INFILE"
echo required outfile: "$OUTFILE"
echo the answer: "$THE_ANSWER"
echo -n do the thing?
if [[ $DO_THE_THING ]]; then
echo " yes, do it"
else
echo " no, do not do it"
fi
echo -n "arg with multiple values: "
for a in "${MULTIPLE[@]}"; do
echo -n "[$a] "
done
echo
#/bin/bash
source$(dirname$0)/argparse.bash | |退出1
argparse“$@”我提出了一个简单的TLDR:;以联合国为例
创建一个名为greeter.sh的bash脚本
#/bin/bash
而getopts“n:”arg;做
案例$arg in
n) 名称=$OPTARG;;
以撒
完成
echo“你好$Name!”
然后,您可以在执行脚本时传递可选参数-n
按如下方式执行脚本:
$ bash greeter.sh -n 'Bob'
输出
$ Hello Bob!
注释
如果要使用多个参数:
在getops“n:”arg:do时扩展,使用更多参数,例如
而getops“n:o:p:”arg:do
使用额外的变量分配扩展case开关。例如o)选项=$OPTARG
和p)参数=$OPTARG
要使脚本可执行,请执行以下操作:
chmod u+x greeter.sh
另存为sample.sh
试着跑步
sh sample.sh -n John
在您的终端中。我在使用带有多个标志的getopts时遇到问题,所以我编写了这段代码。它使用一个模态变量来检测标志,并使用这些标志为变量分配参数
注意,如果一个标志不应该有一个参数,那么除了设置CURRENTFLAG之外,还可以执行其他操作
for MYFIELD in "$@"; do
CHECKFIRST=`echo $MYFIELD | cut -c1`
if [ "$CHECKFIRST" == "-" ]; then
mode="flag"
else
mode="arg"
fi
if [ "$mode" == "flag" ]; then
case $MYFIELD in
-a)
CURRENTFLAG="VARIABLE_A"
;;
-b)
CURRENTFLAG="VARIABLE_B"
;;
-c)
CURRENTFLAG="VARIABLE_C"
;;
esac
elif [ "$mode" == "arg" ]; then
case $CURRENTFLAG in
VARIABLE_A)
VARIABLE_A="$MYFIELD"
;;
VARIABLE_B)
VARIABLE_B="$MYFIELD"
;;
VARIABLE_C)
VARIABLE_C="$MYFIELD"
;;
esac
fi
done
这就是我的解决方案。我希望能够处理不带连字符、带一个连字符和带两个连字符的布尔标志,以及带一个和两个连字符的参数/值赋值
#处理多种类型的参数并打印一些变量
#
#布尔标志
#1)没有连字符
#create将'true'赋值给变量'create'。
#默认值为“创建默认值”。
#delete为变量“delete”赋值为true。
#默认值为“删除默认值”。
#2)一个连字符
#a将'true'赋值给a。默认值为“false”。
#b将'true'赋值给b。默认值为“false”。
#3)两个连字符
#cats将'true'指定给'cats'。默认情况下,未设置。
#狗把“真”指定给“猫”。默认情况下,未设置。
#
#参数值
#1)一个连字符
#c分配您想要的任何值
#d分配您想要的任何值
#
#2)两个连字符
# ... 任何事实上,无论给出什么双连字符参数,都不是
#定义为flag,将使用其后面的下一个参数进行定义。
#
#例如:
#./parser_example.sh delete-a-c VA_1--cats--dir/path/to/dir
解析器(){
#定义带有一个连字符的参数,这些连字符是布尔标志
连字符标志=“a b”
#定义带有两个连字符的参数,这两个连字符是布尔标志
DHYPHEN_FLAGS=“猫狗”
#迭代所有参数
当[$#-gt 0];执行
#处理不带连字符的参数
如果[$1!=“-”*];
$ bash greeter.sh -n 'Bob'
$ Hello Bob!
chmod u+x greeter.sh
#!/bin/bash
if getopts "n:" arg; then
echo "Welcome $OPTARG"
fi
sh sample.sh -n John
for MYFIELD in "$@"; do
CHECKFIRST=`echo $MYFIELD | cut -c1`
if [ "$CHECKFIRST" == "-" ]; then
mode="flag"
else
mode="arg"
fi
if [ "$mode" == "flag" ]; then
case $MYFIELD in
-a)
CURRENTFLAG="VARIABLE_A"
;;
-b)
CURRENTFLAG="VARIABLE_B"
;;
-c)
CURRENTFLAG="VARIABLE_C"
;;
esac
elif [ "$mode" == "arg" ]; then
case $CURRENTFLAG in
VARIABLE_A)
VARIABLE_A="$MYFIELD"
;;
VARIABLE_B)
VARIABLE_B="$MYFIELD"
;;
VARIABLE_C)
VARIABLE_C="$MYFIELD"
;;
esac
fi
done