我有一个使用土帽实现交换机的脚本。然而,我在引用下一个论点时遇到了困难。
我的脚本是支持在本地开发环境上备份我们的网站。我添加了一个-p开关来运行一些部署后的步骤。下面是我的语法:
backport -p /path/to/website_backup.sql.gz因此,在切换之前,我正在测试是否指定了一个文件,并且它是一个正确的文件。因为文件名路径是唯一的参数,我可以假设它是必要的,而且它也是第一个参数($1)。
if [[ $# -eq 0 ]] ; then
echo 'Specifcy the sql file to backport.';
exit 0;
fi
if [[ ! -f "$1" ]]; then
echo "$1 is not a valid file.";
exit 0;
fi我找到了这个答案,它演示了如何使用getopts解析开关参数的示例:
while getopts "p" opt; do
case $opt in
p) p_post_deploy=true ;; # Handle -a
esac
done当然,在实现getopts之后,使用$1作为参数是行不通的。没有开关就没问题。但是,当我添加开关时,它当然是第一个参数,我的脚本正在测试它是否是一个文件。
$ backport -p /path/to/website_backup.sql.gz
-p is not a valid file.因此,随着开关的引入,我不能依赖在命令中特定位置出现的任何参数。硬编码的$2不能工作,因为如果没有开关,文件名参数就不是第二个参数。我想要一个解决方案,允许我接受一个接一个的开关,并允许我在将来引入新的开关,同时只更新代码来处理新的开关本身(而不必重新洗牌以后可能在引入新开关后移动的参数)。
我查看了unix.stackexchange问题的答案,该问题指导我如何使用getopts解析开关。答案之一将$*作为表示其余参数的变量。
if [[ "$*" -eq 0 ]] ; then
echo 'Specifcy the sql file to backport.';
exit 0;
fi然而,当我尝试使用它时,我没有正确地表达语法,并且得到了一个解析错误。
~/scripts/backport: line 14: [[: /d/Downloads/database.sql.gz: syntax error: operand expected (error token is "/d/Downloads/database.sql.gz")如何在getop之后测试文件名参数?
下面是当前版本的脚本:
$ cat backport
#!/bin/bash
set -e
while getopts "p" opt; do
case $opt in
p) p_post_deploy=true ;;
esac
done
shift $(($OPTIND - 1))
# testing what this variable looks like
printf "Remaining arguments are: %s\n" "$*"
if [[ "$*" -eq 0 ]] ; then
echo 'Specifcy the sql file to backport.';
exit 0;
fi
if [[ ! -f "$*" ]]; then
echo "$* is not a valid file.";
exit 0;
fi
drush @local.dev sql-drop -y ;
zcat $1 | drush @local.dev sqlc ;
drush @local.dev cr;
if [ ! -z "$p_post_deploy" ] ; then
echo "Running post-deploy..."
SCRIPT_PATH=$(dirname "$BASH_SOURCE")
source "$SCRIPT_PATH/post-deploy"
post_deploy
fi发布于 2019-10-31 14:33:37
我只能为自己的沟通不善而自责,但克莎拉南达已经给出了我在评论中想要的答案。
在使用getopts解析交换机之后
while getopts "p" opt; do
case $opt in
p) p_post_deploy=true ;;
esac
done这条线
shift "$((OPTIND - 1))"将从参数列表中删除所有开关,以便您可以再次使用位置参数,就像不使用开关一样。
外壳程序不会自动重置OPTIND。你必须手动重置它。
发布于 2019-10-31 13:19:32
测试构造的应用
if [[ "$*" -eq 0 ]]是不正确的。-eq用于整型比较,并且假定$*引用所有剩余参数的参数列表,而不是它们的个数,则测试构造必然会产生语法错误,除非此时剩馀参数的列表恰好包含一个元素,该元素还必须表示整数(这不是您想要实现的)。
现在,对于实际的任务,我认为很难将“非选项参数”(它之前没有“宣布”-)和选项参数混为一谈,只要您允许任意的顺序(即,只要您没有指定文件名必须是最后一个)。如果您想使用getopts,您可能只想让文件名也成为一个选项参数,方法是要求将它指定为-f 。然后你可以用
while getopts "pf:" opt; do
case $opt in
p)
p_post_deploy=true
;;
f)
backportfile=$OPTARG
;;
esac
done如果没有指定文件名,请让getopts自动抱怨。
./test.sh: option requires an argument -- f然后,您还可以稍后测试该文件是否存在,如
if [[ ! -f "$backportfile" ]]
then
echo "$backportfile is not a valid file"
exit 1
fihttps://unix.stackexchange.com/questions/549129
复制相似问题