在 shell 脚本中为变量定义一组值

在 shell 脚本中为变量定义一组值

我想为单个变量定义一组值。例如

singleDigit={0,1,2,3,4,5,6,7,8,9}

如果用户给出 10,它应该退出并出现错误。

如何在不使用循环而是使用数组的情况下实现这一点?

答案1

如果您想将多个值存储到一个变量中,那么您可以使用大批喜欢:

allowed_values=(0 1 2 3 4 5 6 7 8 9)

或者

allowed_values=({0..9})

with bash3+(从现在借用的语法zsh也可以在 中使用ksh93)。

如果您想检查给定的字符串是否在这些值中,您可以定义一个函数,例如:

isin() {
  local s
  for s in "${@:2}"; do
    [[ $1 = "$s" ]] && return 0
  done
  return 1
}

if isin "$input" "${allowed_values[@]}"

(在 中zsh,你可以这样做if ((allowed_values[(eI)$input])))。

请注意,比较是词法的(如 01 != 1)。进行数值比较,您会使用[ "$1" -eq "$s" ] 2> /dev/null(注意是01010而不是8)。不要使用[[ $1 -eq $s ]]或,((s == $1))因为它们会引入任意命令注入漏洞。


如果您想分配一个图案对于要匹配某些输入的变量,您可以使用标量变量并使用extglob以下支持的 2 种(3 种带选项)模式语法之一bash

  • 通配符/全局模式

    pattern='[0-9]'
    

    用作:

    case $input in
      ($pattern) echo OK;;
      (*) echo NOK
    esac
    

    或者

    if [[ $input = $pattern ]]; then
      echo OK
    else
      echo NOK
    fi
    
  • 扩展正则表达式:

    regex='^[0-9]$'
    

    用作:

    if [[ $input =~ $regex ]]; then
      echo OK
    else
      echo NOK
    fi
    

在一般情况下,对于单字符以外的值,您可以使用:

regex='^(one|two|three)$'

而对于模式,您需要以下extglob选项:

shopt -s extglob
pattern='@(one|two|three)'

bash4+使用, or ksh93or 的另一种方法zsh是使用关联数组:

bashksh93

typeset -A allowed_values
allowed_values=([one]=1 [two]=1 [three]=1)
if ((allowed_values[$input])); then
  echo OK
else
  echo NOK
fi

在 中zsh,相同,但赋值语法是:

typeset -A allowed_values
allowed_values=(one 1 two 1 three 1)

(请注意,使用 时bash,不能将空字符串作为允许值)。

答案2

如果只允许输入数字 0 到 9,那么您只需要一个简单的 IF 语句即可。

#!/bin/bash

echo -n Please enter a single digit:
read single_digit
if [ $single_digit -lt 10 ]; then
   echo Thanks for $single_digit
else
   echo Screwball!!! I said SINGLE DIGIT!!
fi

相关内容