script.sh
我有一个这样的shell 脚本:
names=( jack john jerry)
我希望用户输入这三个名称中的任何一个作为其第一个参数,就像:
./script.sh jack
例如,如果用户输入错误
./script.sh kate
它将触发 aexit
并要求用户仅输入这 3 个中的一个。
我应该怎么办?
答案1
names=(jack john jerry);
if [[ " "${names[@]}" " == *" "$1" "* ]] ;then
echo "$1: ok"
else
echo "$1: not recognized. Valid names are:"
echo "${names[@]/%/,}"
exit 1
fi
上面的代码适用于不包含空格的名称。
下面的修改版本可以处理名称中的空格。
names=("flash jack" john jerry);
d=$'\1' # validation delimiter - value is \x01
valid="${names[@]/%/$d}"
valid="$d${valid//$d /$d}"
if [[ $valid == *$d$1$d* ]] ;then
echo "$1: ok"
else
echo "$1: not recognized. Valid names are:"
echo "${names[@]/%/,}"
exit 1
fi
空白感知版本的输出:
flash jack: ok
或者
kate: not recognized. Valid names are:
flash jack, john, jerry,
答案2
这正是case
声明的用途:
#! /bin/bash
case $1 in
[Jj]ack)
echo "You chose Jack!"
;;
[Jj]ohn)
echo "You chose John!"
;;
[Jj]erry)
echo "You chose Jerry!"
;;
## For all other cases
*)
echo 'Please choose one of "John", "Jack" or "Jerry"' >&2
exit 1
esac
$1
case 语句将根据传递给脚本的第一个参数的值运行。如果是jack
or Jack
,则将运行第一个选择,如果是John
orjohn
第二个等等。如果输入了其他内容,则将运行最后一个语句。
答案3
首先,我需要提到的是,足够强大的 shell 脚本可以使用可怕的数组实现,这可能会被视为魔鬼的产物。另外,你没有指出什么 shell,但我假设是 bash。
有很多方法可以做到这一点,但都很丑陋。
1) 迭代数组。它可读且相对干净,但效率低下。
for i in 0 1 2 3 4
do
echo compare ${ARRAY[$i]} perhaps using test or whatever you like
done
2)使用expr一次完成所有操作。这是很脆弱的,如果一个名称是另一个名称的子字符串,就会损坏。这个问题可以解决,但如果涉及到这个问题,我建议使用更好的工具
$ ARRAY=(jack john jerry )
$ expr "${ARRAY[*]}" : '.*jack.*'
15 # it's found
$ expr "${ARRAY[*]}" : '.*sue.*'
0 # not found
其中 jack 或 sue 被 $1 或您要检查的任何参数替换。