我正在尝试使用getopts
创建一个可用作wc
的脚本。问题是当我一起使用两个开关时卡住了。脚本:
while getopts l:w:c: choice
do
case $choice in
l) wc -l $OPTARG;;
w) wc -w $OPTARG;;
c) wc -c $OPTARG;;
?) echo wrong option.
esac
done
当我使用./script.sh -l file
运行此脚本时,它可以正常运行,但是当我使用./script -wl file
时,它只会进入无限循环。任何人都可以解释一下发生了什么以及如何解决它?
答案 0 :(得分:4)
您使用不当。根据{{3}}:
如果一个字母后跟一个冒号,该选项应该有一个 参数。
在您的示例中,您没有传递-w
和-l
选项的参数;
正确用法是:
./script -w file1 -l file2
这将正确处理两个选项。
否则支持不带参数的选项只需使用不带冒号,如下所示:
while getopts "hl:w:c:" choice
这里选项h
不需要参数,但l,w,c将支持一个参数。
答案 1 :(得分:3)
您需要在case语句中构建选项,然后执行wc
:
# Set WC_OPTS to empty string
WC_OPTS=();
while getopts lwc choice
do
case $choice in
l) WC_OPTS+='-l';;
w) WC_OPTS+='-w';;
c) WC_OPTS+='-c';;
?) echo wrong option.
esac
done
# Call wc with the options
shift $((OPTIND-1))
wc "${WC_OPTS[@]}" "$@"
答案 2 :(得分:1)
添加其他评论。 。 。我有用的wc
版本似乎可以处理它的选项:
#!/bin/bash
options=()
files=()
while (( $# > 0 )) ; do
if [[ "$1" = --help || "$1" = --version ]] ; then
wc "$1" # print help-message or version-message
exit
elif [[ "${1:0:1}" = - ]] ; then
while getopts cmlLw opt ; do
if [[ "$opt" = '?' ]] ; then
wc "$1" # print error-message
exit
fi
options+="$opt"
done
shift $((OPTIND-1))
OPTIND=1
else
files+="$1"
shift
fi
done
wc "${options[@]}" "${files[@]}"
(上述内容可以进一步细化,通过为五个可能的选项中的每一个使用单独的变量,突出显示wc
不关心其选项出现的顺序的事实,而不是如果给定选项多次出现,请小心。)
答案 3 :(得分:0)
Got a workaround.
#!/bin/bash
if [ $# -lt 2 ]
then
echo not a proper usage
exit
fi
file=$2
while getopts wlc choice
do
case $choice in
l) wc -l $file
;;
w) wc -w $file
;;
c) wc -c $file
;;
?) echo thats not a correct choice
esac
done
I think I got obsessed with OPTARG, thanks everyone for your kind help