2

I need your help in identifying my problem below,

My intention is to loop the input of the values while at the same time checking the input value if its [0-9] then saves it to a file then sorts the output of it.

My problem is that, whenever i run the script, the values retained as 1 2 3 4 5 not the one that i have inputted, can you help me on this ? i think there is a problem in my variable declaration in the conditional statements, but i dont know any workaround on it.

#!/bin/bash -x

echo > save.txt
validnum='0-9'

   for ((i=1;i<=5;i++))
   do
    read -p "Please enter number $i: " num_$i
    if [[ ! $num_$i =~ [^$validnum$] ]] && [[  $num_$i == "" ]]
    then
            echo "Input numbers have been validated.."
            echo $num_$i >> save.txt
    else
            echo "INVALID CHARACTERS IDENTIFIED.."
            echo "Please review your Input Values"
            exit 0
    fi
done
echo "Sorting values.."
echo "Below are the sorted values"
echo `cat save.txt | sort -n`

here is the expanded version whenever i ran the script.

+ echo
+ validnum=0-9
+ (( i=1 ))
+ (( i<=5 ))
+ read -p 'Please enter number 1: ' num_1
Please enter number 1:
+ [[ ! 1 =~ [^0-9$] ]]
+ [[ ! 1 == '' ]]
+ echo 'Input numbers have been validated..'
Input numbers have been validated..
+ echo 1
+ (( i++ ))
+ (( i<=5 ))
+ read -p 'Please enter number 2: ' num_2
Please enter number 2:
+ [[ ! 2 =~ [^0-9$] ]]
+ [[ ! 2 == '' ]]
+ echo 'Input numbers have been validated..'
Input numbers have been validated..
+ echo 2
+ (( i++ ))
+ (( i<=5 ))
+ read -p 'Please enter number 3: ' num_3
Please enter number 3:
+ [[ ! 3 =~ [^0-9$] ]]
+ [[ ! 3 == '' ]]
+ echo 'Input numbers have been validated..'
Input numbers have been validated..
+ echo 3
+ (( i++ ))
+ (( i<=5 ))
+ read -p 'Please enter number 4: ' num_4
Please enter number 4:
+ [[ ! 4 =~ [^0-9$] ]]
+ [[ ! 4 == '' ]]
+ echo 'Input numbers have been validated..'
Input numbers have been validated..
+ echo 4
+ (( i++ ))
+ (( i<=5 ))
+ read -p 'Please enter number 5: ' num_5
Please enter number 5:
+ [[ ! 5 =~ [^0-9$] ]]
+ [[ ! 5 == '' ]]
+ echo 'Input numbers have been validated..'
Input numbers have been validated..
+ echo 5
+ (( i++ ))
+ (( i<=5 ))
+ echo 'Sorting values..'
Sorting values..
+ echo 'Below are the sorted values'
Below are the sorted values
++ cat save.txt
++ sort -n
+ echo 1 2 3 4 5
1 2 3 4 5
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • 2
    You cannot define dynamic variables like you did with `num_$i`. Probably best to use an array – fedorqui May 03 '17 at 11:46
  • Or just don't use a dynamic variable at all. Just use num as a variable on its own. Can't see the need for a dynamic variable in this instance. – Raman Sailopal May 03 '17 at 11:55
  • any suggestions in replacing the dynamic variable ? i haven't tried Arrays yet , im currently reading about it though – ZaCk Dela Cruz May 03 '17 at 11:58
  • 2
    Technically, you could use indirect parameter expansion to access the variable, although it is clumsy. `tmp=num_$i; if [[ ! ${!tmp} =~ ^$validnum$ ]] && [[ ${!tmp} == "" ]]`. Better to recognize that you don't need separate variables for each iteration of the loop. – chepner May 03 '17 at 12:12
  • 1
    @ZaCkDelaCruz, Here why the statement `[[ ! $num_$i =~ [^$validnum$] ]]` can't work? Because `$num_$i` is expanded two variables `num_` and `i`. Because the name `num_` is a valid variable name in Bash. So it will parse they are two variables. But if you enclosed it with brackets like `${num_$i}` will not work. Because it will complain `bad substitution` error. If you want it work, you can use **Indirect References**. `var="num_$i" ; echo ${!var}` will work. Please refer to [Bash dynamic variable names](http://stackoverflow.com/questions/16553089/bash-dynamic-variable-names). – zhenguoli May 03 '17 at 12:17
  • Thankyou @zhenguoli ill be reading that – ZaCk Dela Cruz May 03 '17 at 12:18
  • Don't forget `eval`! :trollface: ;-) – ghoti May 03 '17 at 12:32

1 Answers1

2

I think you just need the following,

validnum='[0-9]'

read -p "Please enter number $i: " num

if [[ $num =~ ^$validnum{1}$ ]]; then
# rest of the code

to match a single digit from 0-9. Remember I have moved the bracket expressions inside the variable validnum which is more readable than your original version. Plugging this snippet in to your code should fix your problem.

And as discussed over in the comments, you don't need to use the dynamic variables for this requirement of yours.


OP had asked for the explanation of the regex,

RegEx demo

Quoting from the above regular expressions page, explaining the regex ^[0-9]{1}$

^ asserts position at start of the string

Match a single character present in the list below [0-9]{1}

{1} Quantifier — Matches exactly one time (meaningless quantifier)

0-9 a single character in the range between 0 (ASCII 48) and 9 (ASCII 57) (case sensitive)

$ asserts position at the end of the string, or before the line terminator right at the end of the string

Inian
  • 80,270
  • 14
  • 142
  • 161
  • Thank you for the help, i followed the previous comments about the dynamic variable and got the values correct. what i dont understand is the 1 in ^$validnum{1}$ .. what does it do ? is it the length of the input value ? – ZaCk Dela Cruz May 03 '17 at 12:14
  • @ZaCkDelaCruz: See my update, see if it is helpful to you – Inian May 03 '17 at 12:20