如何检查给定参数是否在给定数组中?

如何检查给定参数是否在给定数组中?

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

$1case 语句将根据传递给脚本的第一个参数的值运行。如果是jackor Jack,则将运行第一个选择,如果是Johnorjohn第二个等等。如果输入了其他内容,则将运行最后一个语句。

答案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 或您要检查的任何参数替换。

相关内容