# While \$value != [a..b]

I'm trying to write a function that rewrites a value according to a user's choice. So far it looks like this:

``````while [[ \$code_id != [1-28] ]]; do
echo "1. A"
echo "2. B"
echo "3. C"
echo "4. D"
...
echo "28. Z"
done
echo "INFO: Code is \$code_id."
``````

The user should write a chosen number (1-28). But as a result, code returns me, for a choice. I understand what reason in a condition (while... do), but how I should write this for my code to work?

• What exactly are you trying to do here? (1) you never assign a value to `code_id` and (2) `[1-28]` matches digits 1,2 and 8 only - it is not a numeric range from 1 to 28. Perhaps you are looking for a select loop? Feb 14 at 18:16
• You have 28 letters in your alphabet? Feb 14 at 18:26
• @Rinzwind i have a 10+ letters, what have 1 or 2 the number of digits in a number: if i make a range `\$code_id = [1-9]` i can go in a next stage, but another (`[1-10]`, for example) - this stage is repeating. Feb 14 at 18:56

Here is one possible solution which uses infinite loop that is conditionally break inside.

``````#!/bin/bash

while true
do
read -p "Enter value: " value

if [[ \$value =~ ^[0-9]{1,2}\$ ]] && ((value <= 28)); then break; fi
# does it a number of one or two digits and if true, does it less or equal to 28?
done

echo "The value is: \${value}"
``````

The ranges within the regular expressions doesn't work as these in math. Think about the ranges here as range of sequential characters from the ASCII table. So the character set `[1-28]` consists of `1`, `2` and `8`.

Here is another example. The character set `[a-dz]` includes the characters from the range `a-d`, these are `a`, `b`, `c`, `d`, and the character `z`.

Within the Bash's execute conditional test `[[`, when the `=~` operator is used, the string to the right of the operator is matched as a regular expression.

Looks like you want to use the Bash's `select` builtin:

``````select code_id in {A..Z}; do
[[ -z \$code_id ]] || break
done
echo "INFO: Code is \${code_id}."
``````

Output:

``````1) A    3) C   5) E   7) G   9) I  11) K  13) M  15) O  17) Q  19) S  21) U  23) W  25) Y
2) B    4) D   6) F   8) H  10) J  12) L  14) N  16) P  18) R  20) T  22) V  24) X  26) Z
#? 6
INFO: Code is F.
``````

You may want to limit `COLUMNS` e.g.:

``````COLUMNS=1
select code_id in {A..Z}; do
[[ -z \$code_id ]] || break
done
echo "INFO: Code is \${code_id}."
``````

Output:

`````` 1) A
2) B
3) C
4) D
5) E
6) F
7) G
8) H
9) I
10) J
11) K
12) L
13) M
14) N
15) O
16) P
17) Q
18) R
19) S
20) T
21) U
22) V
23) W
24) X
25) Y
26) Z
#? 17
INFO: Code is Q.
``````

The solution is change a condition to `while [[ \$rep_id -le 0 || \$rep_id -ge 13 ]]; do...`