0

I want to define a set of values for a single variable. E.g.

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

If the user gives 10 it should exit with an error.

How can this be achieved without using a loop, but an array instead?

  • Ok, but if i want to use string then? i.e name={"joy","tom"} and you entered name as harry . It should report error. – Gaurav KS Jul 20 '16 at 10:27
3

If you want to store several values into a variable, that's where you'd use an array like:

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

Or

allowed_values=({0..9})

with bash3+ (syntax borrowed from zsh now also available in ksh93).

And if you want to check whether a given string is among any of those values, you could define a function like:

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

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

(in zsh, you can do if ((allowed_values[(eI)$input]))).

Note that the comparison is lexical (as in 01 != 1). Do do numerical comparison, you'd use [ "$1" -eq "$s" ] 2> /dev/null (note that 010 is 10, not 8). Do not use [[ $1 -eq $s ]] or ((s == $1)) as those introduce arbitrary command injection vulnerabilities.


If you want to assign a pattern to a variable to match against some input, you'd use a scalar variable and use one of the 2 (3 with the extglob option) pattern syntaxes supported by bash:

  • wildcard/glob pattern

    pattern='[0-9]'
    

    Used as:

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

    or

    if [[ $input = $pattern ]]; then
      echo OK
    else
      echo NOK
    fi
    
  • Extended Regular Expression:

    regex='^[0-9]$'
    

    used as:

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

In the general case, for values other than single-character ones, you'd use:

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

And for patterns, you'd need the extglob option:

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

Another approach with bash4+, or ksh93 or zsh is to use an associative array:

With bash, ksh93:

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

In zsh, same but the assignment syntax is:

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

(note that with bash, you can't have the empty string as an allowed value).

  • What version of bash does allowed_valaues=({0..9}) not work on? – 123 Jul 20 '16 at 10:47
  • @123, actually, it seems it's not as recent as I thought. {x..y} was added in bash 3 (2004), – Stéphane Chazelas Jul 20 '16 at 11:17
0

If only the numbers 0 through 9 are allowable as input, all you need is a simple IF statement.

#!/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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.