0

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 "Please select a value..."
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?

3
  • 6
    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, 2022 at 18:16
  • 1
    You have 28 letters in your alphabet?
    – Rinzwind
    Feb 14, 2022 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.
    – Bruyi
    Feb 14, 2022 at 18:56

3 Answers 3

3

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.

2

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.
0

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .