我知道我可以很容易地在bash中获得这样的定位参数:
$0或$1
我希望能够使用这样的标志选项来指定每个参数的使用:
mysql -u user -h host
获得-u参数值和-h参数值的最佳方法是通过标志而不是通过位置?
我知道我可以很容易地在bash中获得这样的定位参数:
$0或$1
我希望能够使用这样的标志选项来指定每个参数的使用:
mysql -u user -h host
获得-u参数值和-h参数值的最佳方法是通过标志而不是通过位置?
当前回答
如果你熟悉Python的argparse,并且不介意调用Python来解析bash参数,我发现有一段代码非常有用,而且超级容易使用,叫做argparse-bash https://github.com/nhoffman/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
其他回答
这个例子使用了Bash内置的getopts命令,来自谷歌Shell样式指南:
a_flag=''
b_flag=''
files=''
verbose='false'
print_usage() {
printf "Usage: ..."
}
while getopts 'abf:v' flag; do
case "${flag}" in
a) a_flag='true' ;;
b) b_flag='true' ;;
f) files="${OPTARG}" ;;
v) verbose='true' ;;
*) print_usage
exit 1 ;;
esac
done
注意:如果一个字符后面跟着一个冒号(例如f:),该选项应该有一个参数。
使用示例:./script -v -a -b -f filename . txt
使用getopts比接受的答案有几个优点:
while条件可读性更强,并显示了接受的选项是什么 清洁代码;不计算参数个数和移位 您可以连接选项(例如-a -b -c→-abc)
然而,一个很大的缺点是它不支持长选项,只支持单字符选项。
#!/bin/bash
if getopts "n:" arg; then
echo "Welcome $OPTARG"
fi
保存为sample.sh 试着跑步
sh sample.sh -n John
在你的终端。
另一种选择是使用类似下面例子的东西,它允许你使用长——image或短的-i标签,还允许编译-i="example.jpg"或单独的-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
您可以将此函数添加到概要文件中,也可以将其放入脚本中。
谢谢!
编辑: 将其保存为一个文件,然后将其作为你的文件执行。
#!/bin/bash
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";
这是我常用的成语:
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语句中匹配它们的值 Shift移走了第一个。您可以在case语句中多次移位以获取多个值。