我试图更好地理解如何使用位置参数作为脚本的参数来编写bash脚本。具体来说,我想了解如何使脚本尽可能用户友好,能够处理来自任何位置的多个参数。其中很多ls -lst
与ls -stl
相同。我决定尝试密码生成器。我不太熟悉编写带参数的脚本。过了一会儿,我决定用if
语句完成整个事情。
注意:要在信用到期时提供信用,下面脚本中的rand_string
功能直接来自this answer。
#!/bin/bash
## grep -v '##' will remove all the comments if you're so inclined :)
usage(){
echo "usage: $0 [n][-c]||[-h]"
}
## Character set used to create random strings
chars=( {a..z} {A..Z} {0..9} \! \" \# \$ \% \& \( \) \* \+ \, \- \. \/ \: \; \< \= \> \? \@ \[ \] \^ \_ \` \{ \| \} \~ \\ )
## Create random string from character set
rand_string() {
local c=$1 ret=
while((c--)); do
ret+=${chars[$((RANDOM%${#chars[@]}))]}; done
printf '%s\n' "$ret"
}
## get a random number between 14-50
length() {
python -S -c "import random; print random.randrange(14,50)"
}
## regular expression to test for valid numbers
re='^[0-9]+$'
## if no options specified
## create a random string of charcters
## of a random length between 14-50 characters
## display password on screen and exit
if [ ! "$1" ]; then
set - "$(length)"
password="$(rand_string "$1")"
echo "$password"
exit
fi
## if option 1 or option 2 is -h or -help
## display usage and exit
if [[ "$1" == -h || "$1" == -help || "$2" == -h || "$2" == -help ]]; then
usage
exit
fi
## if more than 2 options
## exit with error code 1
if [[ $# -gt 2 ]]; then
echo "Invalid number of options specified"
usage
exit 1
fi
## if exactly 2 options
if [[ $# -eq 2 ]]; then
## test if option 1 is a number
## if option 1 is NOT a number
if [[ ! "$1" =~ $re ]]; then
## test if option 1 is -c or -copy
if [[ "$1" == -c || "$1" == -copy ]]; then
## if option 1 is -c or -copy
## test if option 2 is a number
## if 2 is a number and 1 is -c or -copy
## execute the command
if [[ "$2" =~ $re ]]; then
set - "$(length)"
rand_string "$1" | pbcopy
echo "Password copied to clipboard"
exit
## if option 1 is -c or -copy
## but option 2 is NOT a number
## exit script with error code 1
elif [[ ! "$2" =~ $re ]]; then
echo "Unrecognized option \"$2\""
usage
exit 1
fi
else
echo "Unrecognized option \"$1\""
exit 1
fi
## if option 1 is a number
elif [[ "$1" =~ $re ]]; then
## and option 2 is -c or -copy
## execute the command
if [[ "$2" == -c || "$2" == -copy ]]; then
rand_string "$1" | pbcopy
echo "Password copied to clipboard"
exit
## if option 1 is a number
## but option 2 is not -c or -copy
## exit script with error code 1
else
echo "Unrecognized option \"$2\""
usage
exit 1
fi
fi
## if exactly one option specified
elif [[ $# -eq 1 ]]; then
## if option is NOT a number
## check if option is -c or -copy
if [[ ! "$1" =~ $re ]]; then
## if option is -c or -copy
## execute the command
if [[ "$1" == -c || "$1" == -copy ]]; then
set - "$(length)"
rand_string "$1" | pbcopy
echo "Password copied to clipboard"
exit
## if option is neither a number nor -c or -copy
## exit script with error code 1
else
echo "Unrecognized option \"$1\""
usage
exit 1
fi
## if option is a number
## execute the command
elif [[ "$1" =~ $re ]]; then
rand_string "$1"
fi
fi
此脚本有两个可选参数:
任何整数,例如.. 10
,29
,54
以确定字符串的长度
-c
或-copy
将字符串复制到剪贴板
-h
或-help
显示usage
功能
可以从$1
或$2
位置调用上述任何参数。任何这些参数也可以省略。
假设脚本名为password
,则以下任何一种有效用途:
password
password 25
password -c
password 16 -copy
password -c 42
password -help
但是脚本本身是if
语句的一大堆。它冗长,凌乱,难以阅读。
所以我的问题是:如何在不使用这么多if
语句的情况下编写有效用途中显示的相同参数?
我没有要求任何人重写我的剧本。我正在寻找一些指导,以便更好地理解如何正确地做到这一点。
答案 0 :(得分:1)
如果您不想使用getopts
,那么简单的方法就是shift
个参数。
#!/bin/bash
usage(){
echo "usage: $0 [n][-c]||[-h]" >&2
exit 1
}
declare copy=
declare argument=
while [ "$1" ]; do
case "$1" in
-h|-help)
usage
;;
-c|-copy)
copy=1
;;
*)
[[ "$1" =~ ^[0-9]+$ ]] || usage
argument="$1"
;;
esac
shift
done
[ "$argument" ] || argument=$(length)
if [ "$copy" ]; then
rand_string "$argument" | pbcopy
else
rand_string "$argument"
fi