假设有以下情况:
#!/bin/sh
case $1 in
e|ex|exa|exam|examp|exampl|example) echo "OK"
;;
t|te|tes|test) echo "Also OK"
;;
*) echo "Error!"
;;
esac
对于这种情况,是否有更优雅且同时符合 POSIX 标准的解决方案(即没有 bash、zsh 等)?
PS 不需要exampleeee
或Exam
工作。
答案1
你可以做的是扭转比较:
case "example" in
"$1"*) echo OK ;;
*) echo Error ;;
esac
通过多个单词,您可以坚持自己最初的想法
case "$1" in
e|ex|exa|exam|examp|exampl|example) : ;;
t|te|tes|test) : ;;
f|fo|foo) : ;;
*) echo error ;;
esac
或使用循环和“布尔”变量
match=""
for word in example test foo; do
case "$word" in
"$1"*) match=$word; break ;;
esac
done
if [ -n "$match" ]; then
echo "$1 matches $match"
else
echo Error
fi
您可以决定哪个更好。我觉得第一个很优雅。
答案2
你提到了“选项”在评论中,这让我觉得你可能正在尝试解析命令行选项。由于 POSIXgetopts
实用程序无法解析“长选项”,例如--test
or --example
,我们可以要求 GNUgetopt
为我们解析它们。
以下是一个 shell 脚本,它采用短选项-e
和-t
,以及相应的“长选项”--example
和--test
。长选项可以在命令行上指定为完整选项字符串的任何前缀字符串,例如--e
等都--ex
将解析为--example
。在下面的代码中,--test
/-t
选项采用强制参数,由:
相应的长选项字符串和短选项字符串后面的尾随表示。
GNU getopt
( 的一部分util-linux
)用于解析命令行。
#!/bin/sh
opts=$( getopt -o et: -l example,test: -- "$@" )
if [ "$?" -ne 0 ]; then
echo 'Error in getopt' >&2
exit 1
fi
eval set -- "$opts"
unset opts
unset testarg
while true; do
case "$1" in
-e|--example)
echo 'Example option'
shift
;;
-t|--test)
echo 'Test option'
testarg=$2
shift 2
;;
--)
shift
break
;;
*)
echo 'Command line parsing error' >&2
exit 1
esac
done
if [ -n "$testarg" ]; then
printf 'Test argument = "%s"\n' "$testarg"
fi
测试:
$ ./script -e
Example option
$ ./script --exa
Example option
$ ./script --exa -t hello
Example option
Test option
Test argument = "hello"
$ ./script --exa --te='hello world'
Example option
Test option
Test argument = "hello world"
$ ./script -et 'hello world'
Example option
Test option
Test argument = "hello world"
$ ./script -eethello
Example option
Example option
Test option
Test argument = "hello"