我有一个脚本,我想根据一个参数进行分支。
基本上这个参数就像一个布尔值。但我不希望用户只在 shell run 命令中键入任何垃圾并将其解释为 true。
或者我不想要一些需要考虑区分大小写问题等的字符串。
我想要的最终结果是:
some_script.sh arg1 arg2 arg3 --remove
以便:
PARAM1="$1"
PARAM2="$2"
PARAM3="$3"
REMOVE=?--> what here
if [ $REMOVE ]; then
# remove some files
fi
答案1
您只需检查该字符串是否--remove
在脚本的位置参数中即可。使用正则表达式匹配运算符的 bash 版本=~
:
#!/bin/bash
if [[ $@ =~ --remove ]]; then
echo "removing files"
fi
exit
POSIX 版本:
#!/bin/sh
for arg in "$@"; do
if [ "$arg" = "--remove" ]; then
echo "removing files"
fi
done
exit
答案2
虽然$1
和 朋友对于具有一组固定参数的脚本工作得相当好,但对于具有动态参数的脚本来说,它们并不是真正工作得那么好。为此,您需要使用循环和 case 结构:
REMOVE=
for arg in "$@"; do
case "$arg" in
--remove)
REMOVE=1
;;
*)
if [ ! -z "$REMOVE" ]; then
# whatever you need to do to remove
else
# whatever you need to do if you do not want to remove
fi
;;
esac
done
如果您记录 --remove 仅适用于其后的参数,则此方法效果很好;这将允许您拥有一个混合命令行,其中删除适用于某些参数,但不适用于其他参数:
script.sh arg1 arg2 --remove arg3
在上面的示例中,--remove
适用于 arg3,但不适用于 arg1 或 arg2。您--noremove
也可以向案例结构添加对命令行选项的支持:
case "$arg" in
--noremove)
REMOVE=
;;
--remove)
# ... rest of the case remains as is from before
esac
这将允许这样的事情:
script.sh --remove arg1 --noremove arg2 --remove arg3
在该示例中,该--remove
选项适用于 arg1 和 arg3,但不适用于 arg2。
最后,如果您希望--remove
应用到任何参数,无论它出现在命令行中的哪个位置,那么最简单的前进方法可能是使用getopt(1)
:
# reorder the command line so that option arguments come first
# and non-option arguments come second, separated by "--"
PARSED=$(getopt -o '' --long remove -n scriptname.sh -- "$@")
# overwrite $@ with the contents of the newly created $PARSED
# Note the quotes; they are essential
eval set -- "$PARSED"
REMOVE=
while true; do
case "$1" in
--remove)
REMOVE=1
shift
;;
--)
shift; break;
esac
done
for arg in "$@"; do
if [ ! -z "$REMOVE" ]; then
# whatever you need to do to remove
else
# the other thing
fi
done
的参数-o
采用短选项,因此如果您愿意,getopt
可以使用-r
而不是。--remove
当您希望选项(可选)具有参数等时,Getopt 还具有一些额外的选项,并且当用户提供脚本无法识别的选项时,允许免费提供基本用法输出。 GNU getopt 附带了一个示例,它显示了所有的可能性;在 Debian(及其衍生版本)上,您可以找到它/usr/share/doc/util-linux/getopt-parse.bash