我正在编写一个使用长选项和短标志的 bash 脚本。由于我想要长选项,所以我不能使用getopts
。我尝试使用以下代码:
while test -n "$1"; do
case "$1" in
-o|--override) NO_CHANGE=yes;shift 1;;
-r|--reset) OV_RESET=yes;shift 1;;
-h|--help) hthemehelp;shift 1;;
*) break;;
esac
done
myscr -o -r
当我像或一样调用它时,它可以工作myscr -h
,但是当我尝试myscr -or
程序仅运行它的正常行为时,myscr -or -h
它在运行之前退出循环-h
。 用 替换break
只会continue
导致myscr -or
和myscr -or -h
挂起。
答案1
试穿一下这个尺码:
#!/bin/bash
pleasereset=1
while test -n "$1"; do
pleaseshift=0
[[ pleasereset -eq 1 ]] && thisvar=$1 && pleasereset=0;
case "$thisvar" in
-o*|--override) echo "override!"; pleaseshift=1;;
-r*|--reset) echo "reset!"; pleaseshift=1;;
-h*|--help) echo "help!"; pleaseshift=1;;
*) break ;;
esac
if [[ "$pleaseshift" = "1" ]];
then
testvar=${thisvar##-}
if [[ ${#testvar} -gt 1 ]] && [[ ! ${thisvar} = --* ]];
then
thisvar=-$( echo "$testvar" | cut -c 2- )
else
shift 1; pleasereset=1;
fi
fi
done
请注意,在第一个不匹配任何特定情况的参数处,参数解析将停止,因此 a./foobar.sh -o --help -s -r
将不会处理-r
。这可以通过将*) break;;
行更改为错误处理来调整,但请记住将pleaseshift=1
!
答案2
也许添加您想要的行就足够了:
while test -n "$1"; do
case "$1" in
-or|-ro) OV_RESET=yes;NO_CHANGE=yes;shift 1;;
-o|--override) NO_CHANGE=yes;shift 1;;
-r|--reset) OV_RESET=yes;shift 1;;
-h|--help) hthemehelp;shift 1;;
*) break;;
esac
done
或者,更复杂一点,你可以将case
块放在一个函数中,shift 1
该函数位于该块之外,但仍在 while 内。
对于加倍选项(-or
,,-oh
不是长选项之一,您可以对每个字母递归调用相同的函数case *)
...如果您刚刚将其$1
作为长选项处理,则需要一个标志。在这种情况下,然而,由于打印错误,您的脚本会暴露出不良行为(例如,如果我写-overrider I will process
-o -v -e -r -d`...)