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

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.